From 6523a605c20a18b48000d578aebf71763f2a7537 Mon Sep 17 00:00:00 2001 From: Andriy Berestovskyy Date: Thu, 4 Apr 2019 18:54:26 +0200 Subject: [PATCH 001/206] Fix dependency in README This commit fixes #256 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8395359f..6075d836 100644 --- a/README.md +++ b/README.md @@ -119,7 +119,7 @@ demonstrated with the sample server included in this repository: cc_binary( name = "sample_server", srcs = ["sample_server.cc"], - deps = ["@com_github_jupp0r_prometheus_cpp//:prometheus_cpp"], + deps = ["@com_github_jupp0r_prometheus_cpp//:pull"], ) ``` From 17071f49a60949e149f88eb3d441561f34bf0abd Mon Sep 17 00:00:00 2001 From: Sathiyan Sivathas Date: Thu, 11 Apr 2019 17:49:54 +0100 Subject: [PATCH 002/206] Only check label names when inserting a metric into a family --- core/include/prometheus/family.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/core/include/prometheus/family.h b/core/include/prometheus/family.h index bb4a9500..f3ed380b 100644 --- a/core/include/prometheus/family.h +++ b/core/include/prometheus/family.h @@ -146,13 +146,6 @@ template template T& Family::Add(const std::map& labels, Args&&... args) { -#ifndef NDEBUG - for (auto& label_pair : labels) { - auto& label_name = label_pair.first; - assert(CheckLabelName(label_name)); - } -#endif - auto hash = detail::hash_labels(labels); std::lock_guard lock{mutex_}; auto metrics_iter = metrics_.find(hash); @@ -166,6 +159,13 @@ T& Family::Add(const std::map& labels, #endif return *metrics_iter->second; } else { +#ifndef NDEBUG + for (auto& label_pair : labels) { + auto& label_name = label_pair.first; + assert(CheckLabelName(label_name)); + } +#endif + auto metric = metrics_.insert(std::make_pair(hash, detail::make_unique(args...))); assert(metric.second); From d4fb28dddb41897a77e47f61f545e5e43e472b42 Mon Sep 17 00:00:00 2001 From: kubov Date: Mon, 15 Apr 2019 17:07:40 +0000 Subject: [PATCH 003/206] Update README.md example. --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6075d836..2debd974 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,7 @@ this repo to your project as a dependency. Just add the following to your `WORKSPACE`: ```python +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file") http_archive( name = "com_github_jupp0r_prometheus_cpp", strip_prefix = "prometheus-cpp-master", @@ -119,7 +120,7 @@ demonstrated with the sample server included in this repository: cc_binary( name = "sample_server", srcs = ["sample_server.cc"], - deps = ["@com_github_jupp0r_prometheus_cpp//:pull"], + deps = ["@com_github_jupp0r_prometheus_cpp//pull:pull"], ) ``` From eebccaadaaadebc1bb696f5aafc1fdc2c91898be Mon Sep 17 00:00:00 2001 From: kubov Date: Mon, 15 Apr 2019 17:45:07 +0000 Subject: [PATCH 004/206] Simplify deps definition in the example. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2debd974..b85101a5 100644 --- a/README.md +++ b/README.md @@ -120,7 +120,7 @@ demonstrated with the sample server included in this repository: cc_binary( name = "sample_server", srcs = ["sample_server.cc"], - deps = ["@com_github_jupp0r_prometheus_cpp//pull:pull"], + deps = ["@com_github_jupp0r_prometheus_cpp//pull"], ) ``` From 21e6055863767b25ba03cabf9c7bda7164c6711c Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 27 Apr 2019 19:23:00 +0200 Subject: [PATCH 005/206] cmake: Link Google Benchmark library against pthread Fixes: #264 --- cmake/FindGoogleBenchmark.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmake/FindGoogleBenchmark.cmake b/cmake/FindGoogleBenchmark.cmake index 6b50152c..4aa59ce5 100644 --- a/cmake/FindGoogleBenchmark.cmake +++ b/cmake/FindGoogleBenchmark.cmake @@ -2,12 +2,15 @@ find_library(GoogleBenchmark_LIBRARY NAMES benchmark) find_path(GoogleBenchmark_INCLUDE_DIR benchmark/benchmark.h) mark_as_advanced(GoogleBenchmark_LIBRARY GoogleBenchmark_INCLUDE_DIR) +find_package(Threads QUIET) + include(FindPackageHandleStandardArgs) find_package_handle_standard_args(GoogleBenchmark FOUND_VAR GoogleBenchmark_FOUND REQUIRED_VARS GoogleBenchmark_LIBRARY GoogleBenchmark_INCLUDE_DIR + Threads_FOUND ) if(GoogleBenchmark_FOUND) @@ -18,6 +21,7 @@ if(GoogleBenchmark_FOUND) add_library(Google::Benchmark UNKNOWN IMPORTED) set_target_properties(Google::Benchmark PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${GoogleBenchmark_INCLUDE_DIR}" + INTERFACE_LINK_LIBRARIES "Threads::Threads" IMPORTED_LINK_INTERFACE_LANGUAGES "CXX" IMPORTED_LOCATION "${GoogleBenchmark_LIBRARY}" ) From 4a0ee8d8793552d6670c382e86ad23bf6394d361 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 27 Apr 2019 19:44:58 +0200 Subject: [PATCH 006/206] Correct copyright in license file (Fixes: #265) --- LICENSE | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 8aa26455..0e08d61d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,10 @@ MIT License -Copyright (c) [year] [fullname] +Copyright (c) 2016-2019 Jupp Mueller +Copyright (c) 2017-2019 Gregor Jasny + +And many contributors, see +https://github.com/jupp0r/prometheus-cpp/graphs/contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 60ab357445744fcf5548425fcbd1bc80bbe947d3 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 27 Apr 2019 20:01:23 +0200 Subject: [PATCH 007/206] CMake: Use CMake package config file exported by Google Benchmark --- .travis.yml | 1 + CMakeLists.txt | 2 +- cmake/FindGoogleBenchmark.cmake | 29 ----------------------------- core/CMakeLists.txt | 2 +- core/benchmarks/CMakeLists.txt | 2 +- 5 files changed, 4 insertions(+), 32 deletions(-) delete mode 100644 cmake/FindGoogleBenchmark.cmake diff --git a/.travis.yml b/.travis.yml index a3c68891..b68487b7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,6 +37,7 @@ addons: packages: - cmake - bazelbuild/tap/bazel + - google-benchmark - prometheus - telegraf taps: diff --git a/CMakeLists.txt b/CMakeLists.txt index 94dc1e12..1bda3d24 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,7 @@ if(ENABLE_TESTING) else() find_package(GTest 1.8.1 CONFIG REQUIRED) endif() - find_package(GoogleBenchmark) + find_package(benchmark CONFIG) enable_testing() endif() diff --git a/cmake/FindGoogleBenchmark.cmake b/cmake/FindGoogleBenchmark.cmake deleted file mode 100644 index 4aa59ce5..00000000 --- a/cmake/FindGoogleBenchmark.cmake +++ /dev/null @@ -1,29 +0,0 @@ -find_library(GoogleBenchmark_LIBRARY NAMES benchmark) -find_path(GoogleBenchmark_INCLUDE_DIR benchmark/benchmark.h) -mark_as_advanced(GoogleBenchmark_LIBRARY GoogleBenchmark_INCLUDE_DIR) - -find_package(Threads QUIET) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(GoogleBenchmark - FOUND_VAR GoogleBenchmark_FOUND - REQUIRED_VARS - GoogleBenchmark_LIBRARY - GoogleBenchmark_INCLUDE_DIR - Threads_FOUND -) - -if(GoogleBenchmark_FOUND) - set(GoogleBenchmark_LIBRARIES ${GoogleBenchmark_LIBRARY}) - set(GoogleBenchmark_INCLUDE_DIRS ${GoogleBenchmark_INCLUDE_DIR}) - - if(NOT TARGET Google::Benchmark) - add_library(Google::Benchmark UNKNOWN IMPORTED) - set_target_properties(Google::Benchmark PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${GoogleBenchmark_INCLUDE_DIR}" - INTERFACE_LINK_LIBRARIES "Threads::Threads" - IMPORTED_LINK_INTERFACE_LANGUAGES "CXX" - IMPORTED_LOCATION "${GoogleBenchmark_LIBRARY}" - ) - endif() -endif() diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 219cc82c..f520ceec 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -50,6 +50,6 @@ if(ENABLE_TESTING) add_subdirectory(tests) endif() -if(GoogleBenchmark_FOUND) +if(benchmark_FOUND) add_subdirectory(benchmarks) endif() diff --git a/core/benchmarks/CMakeLists.txt b/core/benchmarks/CMakeLists.txt index dd9f2230..c0d2dd09 100644 --- a/core/benchmarks/CMakeLists.txt +++ b/core/benchmarks/CMakeLists.txt @@ -13,7 +13,7 @@ add_executable(benchmarks target_link_libraries(benchmarks PRIVATE ${PROJECT_NAME}::core - Google::Benchmark + benchmark::benchmark ) add_test( From d30894dc987b67b564fcb217ac4af8e6ed84598d Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 27 Apr 2019 20:55:38 +0200 Subject: [PATCH 008/206] cmake: print feature summary --- CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1bda3d24..20d7190e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,3 +82,11 @@ install( FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" ) + +# summary + +include(FeatureSummary) +add_feature_info("Pull" "${ENABLE_PULL}" "support for pulling metrics") +add_feature_info("Push" "${ENABLE_PUSH}" "support for pushing metrics to a push-gateway") +add_feature_info("Compression" "${ENABLE_COMPRESSION}" "support for zlib compression of metrics") +feature_summary(WHAT ALL) From 17e728292770f61fdcf3eda250096dc761056a35 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 28 Apr 2019 12:19:51 +0200 Subject: [PATCH 009/206] travis: build on xenial --- .travis.yml | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index b68487b7..e8ec32ec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,7 @@ sudo: required -dist: trusty +dist: xenial language: c++ -before_install: - - echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- - env: global: - secure: "DwlWRs05m1pw3/NprZdVRy3Vog7k+KYIW4O1YQczbKk0t64vYLJMxMh9D8HrngnUv1UDOOU2orEO/hYYjlmiNRqoMA0Me+q9ndqEGjdCvFketH7zYpPXMxV/Uk1E7yYK60CJYbCFK7NossBWlBwSIETUNXXz1MhqF4c7SwDCTQk6ybPUThJVI3/nZLC4Wn9DB4pxPkEZaXJLL3HU0vXH1r0vKRFsjBU0OtDx1KQgtFYVmWbmd7tpxAlDfI11HJjpaoFD6HHcTlwvM5Ogj4lWL8Ze3glJsSsAYntEqgm7GQa4tYWsYmvGC5554WwIQ/0cDsSTLZjk2+FtSGmJpxdwXwmfOzzVjt7Ise7KG2Zg+CZ/IwF9VpwP2xmH/ug926sJDIjMmehZx2eetDzwY3oB3g3AF+JJIoaDF14Skt6QXEFWm/s/PiSQwkenMF80xzUufB7CRCVLR054HfJsQ0m5O8bNtUjyH7byZwOjvz8t/VdlnfFn5Ccs4tniOK6iiwvKmGAaakv6pfA7xKpRbExFkgPoTmejeQX83Ee1/A4JySMPTxkHPsJbMhimpMdbLVJTh9mKJxo2kleCC0MKB7OwTyNwUdR8+nqoZpUknGX6BrGY+R6ou3xlNYRUM9LCxxBKBJB05CswbhRWroun9fbpDTzBz3XPwBjiVTlxUc/YnXA=" @@ -19,15 +16,15 @@ addons: sources: - sourceline: 'deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8' key_url: 'https://storage.googleapis.com/bazel-apt/doc/apt-key.pub.gpg' - - sourceline: 'deb https://repos.influxdata.com/ubuntu trusty stable' + - sourceline: 'deb https://repos.influxdata.com/ubuntu xenial stable' key_url: 'https://repos.influxdata.com/influxdb.key' packages: - bazel - - cmake3 + - cmake - curl - doxygen - - g++-4.8 - - gcc-4.8 + - g++ + - gcc - git - lcov - libcurl4-openssl-dev From afef90f43e3bb704a84509c7f685f571bb5cfcf0 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 28 Apr 2019 16:16:18 +0200 Subject: [PATCH 010/206] core: Improve test coverage --- core/tests/CMakeLists.txt | 1 + core/tests/builder_test.cc | 96 ++++++++++++++++++++++++++++++++++++++ core/tests/gauge_test.cc | 14 ++++++ 3 files changed, 111 insertions(+) create mode 100644 core/tests/builder_test.cc diff --git a/core/tests/CMakeLists.txt b/core/tests/CMakeLists.txt index 881695ba..ee94919b 100644 --- a/core/tests/CMakeLists.txt +++ b/core/tests/CMakeLists.txt @@ -1,5 +1,6 @@ add_executable(prometheus_test + builder_test.cc check_names_test.cc counter_test.cc family_test.cc diff --git a/core/tests/builder_test.cc b/core/tests/builder_test.cc new file mode 100644 index 00000000..c7407b58 --- /dev/null +++ b/core/tests/builder_test.cc @@ -0,0 +1,96 @@ +#include "prometheus/counter.h" +#include "prometheus/gauge.h" +#include "prometheus/histogram.h" +#include "prometheus/registry.h" +#include "prometheus/summary.h" + +#include +#include + +namespace prometheus { +namespace { + +class BuilderTest : public testing::Test { + protected: + std::vector getExpectedLabels() { + std::vector labels; + + auto gen = [](std::pair p) { + return ClientMetric::Label{p.first, p.second}; + }; + + std::transform(std::begin(const_labels), std::end(const_labels), + std::back_inserter(labels), gen); + std::transform(std::begin(more_labels), std::end(more_labels), + std::back_inserter(labels), gen); + + return labels; + } + + void verifyCollectedLabels() { + const auto collected = registry.Collect(); + + ASSERT_EQ(1U, collected.size()); + EXPECT_EQ(name, collected.at(0).name); + EXPECT_EQ(help, collected.at(0).help); + ASSERT_EQ(1U, collected.at(0).metric.size()); + + EXPECT_THAT(collected.at(0).metric.at(0).label, + testing::UnorderedElementsAreArray(expected_labels)); + } + + Registry registry; + + const std::string name = "some_name"; + const std::string help = "Additional description."; + const std::map const_labels = {{"key", "value"}}; + const std::map more_labels = {{"name", "test"}}; + const std::vector expected_labels = getExpectedLabels(); +}; + +TEST_F(BuilderTest, build_counter) { + auto& family = BuildCounter() + .Name(name) + .Help(help) + .Labels(const_labels) + .Register(registry); + family.Add(more_labels); + + verifyCollectedLabels(); +} + +TEST_F(BuilderTest, build_gauge) { + auto& family = BuildGauge() + .Name(name) + .Help(help) + .Labels(const_labels) + .Register(registry); + family.Add(more_labels); + + verifyCollectedLabels(); +} + +TEST_F(BuilderTest, build_histogram) { + auto& family = BuildHistogram() + .Name(name) + .Help(help) + .Labels(const_labels) + .Register(registry); + family.Add(more_labels, Histogram::BucketBoundaries{1, 2}); + + verifyCollectedLabels(); +} + +TEST_F(BuilderTest, build_summary) { + auto& family = BuildSummary() + .Name(name) + .Help(help) + .Labels(const_labels) + .Register(registry); + family.Add(more_labels, Summary::Quantiles{}); + + verifyCollectedLabels(); +} + +} // namespace +} // namespace prometheus diff --git a/core/tests/gauge_test.cc b/core/tests/gauge_test.cc index fdcd34bf..0183f761 100644 --- a/core/tests/gauge_test.cc +++ b/core/tests/gauge_test.cc @@ -30,6 +30,13 @@ TEST(GaugeTest, inc_multiple) { EXPECT_EQ(gauge.Value(), 7.0); } +TEST(GaugeTest, inc_negative_value) { + Gauge gauge; + gauge.Increment(5.0); + gauge.Increment(-5.0); + EXPECT_EQ(gauge.Value(), 5.0); +} + TEST(GaugeTest, dec) { Gauge gauge; gauge.Set(5.0); @@ -37,6 +44,13 @@ TEST(GaugeTest, dec) { EXPECT_EQ(gauge.Value(), 4.0); } +TEST(GaugeTest, dec_negative_value) { + Gauge gauge; + gauge.Set(5.0); + gauge.Decrement(-1.0); + EXPECT_EQ(gauge.Value(), 5.0); +} + TEST(GaugeTest, dec_number) { Gauge gauge; gauge.Set(5.0); From 19125a480b35ba15e1b670fd10887624c8ed8859 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Mon, 6 May 2019 21:04:17 +0200 Subject: [PATCH 011/206] push: Forward libcurl errors to caller --- push/src/gateway.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/push/src/gateway.cc b/push/src/gateway.cc index bc137ec4..8aae31a2 100644 --- a/push/src/gateway.cc +++ b/push/src/gateway.cc @@ -139,7 +139,7 @@ int Gateway::push(HttpMethod method) { auto uri = getUri(wcollectable); auto status_code = performHttpRequest(method, uri, body); - if (status_code >= 400) { + if (status_code < 100 || status_code >= 400) { return status_code; } } @@ -176,7 +176,7 @@ std::future Gateway::async_push(HttpMethod method) { for (auto& future : lfutures) { auto status_code = future.get(); - if (status_code >= 400) { + if (status_code < 100 || status_code >= 400) { final_status_code = status_code; } } From 5d7f4b287e615a3a0c7e68a85562cff05b8c802f Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Mon, 6 May 2019 21:25:21 +0200 Subject: [PATCH 012/206] push: Pass method, uri, body by value Closes: #272 --- push/src/gateway.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/push/src/gateway.cc b/push/src/gateway.cc index 8aae31a2..5cf7c3e9 100644 --- a/push/src/gateway.cc +++ b/push/src/gateway.cc @@ -165,7 +165,7 @@ std::future Gateway::async_push(HttpMethod method) { auto body = serializer.Serialize(metrics); auto uri = getUri(wcollectable); - futures.push_back(std::async(std::launch::async, [&] { + futures.push_back(std::async(std::launch::async, [method, uri, body, this] { return performHttpRequest(method, uri, body); })); } From f06970ff073f835a8401135f926a11535ae91261 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Mon, 6 May 2019 21:51:58 +0200 Subject: [PATCH 013/206] push: allocate body on the heap --- push/src/gateway.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/push/src/gateway.cc b/push/src/gateway.cc index 5cf7c3e9..d23e8e3c 100644 --- a/push/src/gateway.cc +++ b/push/src/gateway.cc @@ -1,6 +1,7 @@ #include "prometheus/gateway.h" +#include #include #include "prometheus/client_metric.h" @@ -162,11 +163,11 @@ std::future Gateway::async_push(HttpMethod method) { } auto metrics = collectable->Collect(); - auto body = serializer.Serialize(metrics); + auto body = std::make_shared(serializer.Serialize(metrics)); auto uri = getUri(wcollectable); futures.push_back(std::async(std::launch::async, [method, uri, body, this] { - return performHttpRequest(method, uri, body); + return performHttpRequest(method, uri, *body); })); } From 87e024bd42d84d3f4488ac0387159484f78e3797 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 8 Jun 2019 21:18:56 +0200 Subject: [PATCH 014/206] push: Print push return code in example --- push/tests/integration/sample_client.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/push/tests/integration/sample_client.cc b/push/tests/integration/sample_client.cc index 7a0c283c..abad8e87 100644 --- a/push/tests/integration/sample_client.cc +++ b/push/tests/integration/sample_client.cc @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -56,7 +57,8 @@ int main() { second_counter.Increment(); // push metrics - gateway.Push(); + auto returnCode = gateway.Push(); + std::cout << "returnCode is " << returnCode << std::endl; } return 0; } From 2b400ecae7914e196a9f165a7f4823ca10ee41a8 Mon Sep 17 00:00:00 2001 From: mkenigs <40775676+mkenigs@users.noreply.github.com> Date: Mon, 24 Jun 2019 10:11:18 -0700 Subject: [PATCH 015/206] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b85101a5..1e0723f5 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ other push/pull collections can be added as plugins. ## Usage +See https://jupp0r.github.io/prometheus-cpp for more detailed interface documentation. + ``` c++ #include #include From 4bbefe0c3d2743dea591b8f63d3a57d96ac55a59 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Mon, 24 Jun 2019 21:23:13 +0200 Subject: [PATCH 016/206] travis: update homebrew to avoid error --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index e8ec32ec..a3b4d522 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,6 +31,7 @@ addons: - python-pip - telegraf homebrew: + update: true packages: - cmake - bazelbuild/tap/bazel From 1b1a99d86287c98efb0dfb1e7e0ae5c3ddccdbcc Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 30 Jun 2019 20:49:34 +0200 Subject: [PATCH 017/206] core: Serialize floating values locale-independent Closes: #281 --- core/src/text_serializer.cc | 75 ++++++++++++++++------------------- core/tests/CMakeLists.txt | 1 + core/tests/serializer_test.cc | 60 ++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 41 deletions(-) create mode 100644 core/tests/serializer_test.cc diff --git a/core/src/text_serializer.cc b/core/src/text_serializer.cc index 432379b8..fc84c41e 100644 --- a/core/src/text_serializer.cc +++ b/core/src/text_serializer.cc @@ -2,6 +2,7 @@ #include #include +#include #include namespace prometheus { @@ -9,59 +10,48 @@ namespace prometheus { namespace { // Write a double as a string, with proper formatting for infinity and NaN -std::string ToString(double v) { - if (std::isnan(v)) { - return "Nan"; +void WriteValue(std::ostream& out, double value) { + if (std::isnan(value)) { + out << "Nan"; + } else if (std::isinf(value)) { + out << (value < 0 ? "-Inf" : "+Inf"); + } else { + auto saved_flags = out.setf(std::ios::fixed, std::ios::floatfield); + out << value; + out.setf(saved_flags, std::ios::floatfield); } - if (std::isinf(v)) { - return (v < 0 ? "-Inf" : "+Inf"); - } - return std::to_string(v); } -const std::string& EscapeLabelValue(const std::string& value, - std::string* tmp) { - bool copy = false; - for (size_t i = 0; i < value.size(); ++i) { - auto c = value[i]; +void WriteValue(std::ostream& out, const std::string& value) { + for (auto c : value) { if (c == '\\' || c == '"' || c == '\n') { - if (!copy) { - tmp->reserve(value.size() + 1); - tmp->assign(value, 0, i); - copy = true; - } - if (c == '\\') { - tmp->append("\\\\"); - } else if (c == '"') { - tmp->append("\\\""); - } else { - tmp->append("\\\n"); - } - } else if (copy) { - tmp->push_back(c); + out << "\\"; } + out << c; } - return copy ? *tmp : value; } // Write a line header: metric name and labels +template void WriteHead(std::ostream& out, const MetricFamily& family, const ClientMetric& metric, const std::string& suffix = "", const std::string& extraLabelName = "", - const std::string& extraLabelValue = "") { + const T& extraLabelValue = T()) { out << family.name << suffix; if (!metric.label.empty() || !extraLabelName.empty()) { out << "{"; const char* prefix = ""; - std::string tmp; + for (auto& lp : metric.label) { - out << prefix << lp.name << "=\"" << EscapeLabelValue(lp.value, &tmp) - << "\""; + out << prefix << lp.name << "=\""; + WriteValue(out, lp.value); + out << "\""; prefix = ","; } if (!extraLabelName.empty()) { - out << prefix << extraLabelName << "=\"" - << EscapeLabelValue(extraLabelValue, &tmp) << "\""; + out << prefix << extraLabelName << "=\""; + WriteValue(out, extraLabelValue); + out << "\""; } out << "}"; } @@ -79,14 +69,14 @@ void WriteTail(std::ostream& out, const ClientMetric& metric) { void SerializeCounter(std::ostream& out, const MetricFamily& family, const ClientMetric& metric) { WriteHead(out, family, metric); - out << ToString(metric.counter.value); + WriteValue(out, metric.counter.value); WriteTail(out, metric); } void SerializeGauge(std::ostream& out, const MetricFamily& family, const ClientMetric& metric) { WriteHead(out, family, metric); - out << ToString(metric.gauge.value); + WriteValue(out, metric.gauge.value); WriteTail(out, metric); } @@ -98,12 +88,12 @@ void SerializeSummary(std::ostream& out, const MetricFamily& family, WriteTail(out, metric); WriteHead(out, family, metric, "_sum"); - out << ToString(sum.sample_sum); + WriteValue(out, sum.sample_sum); WriteTail(out, metric); for (auto& q : sum.quantile) { - WriteHead(out, family, metric, "", "quantile", ToString(q.quantile)); - out << ToString(q.value); + WriteHead(out, family, metric, "", "quantile", q.quantile); + WriteValue(out, q.value); WriteTail(out, metric); } } @@ -111,7 +101,7 @@ void SerializeSummary(std::ostream& out, const MetricFamily& family, void SerializeUntyped(std::ostream& out, const MetricFamily& family, const ClientMetric& metric) { WriteHead(out, family, metric); - out << ToString(metric.untyped.value); + WriteValue(out, metric.untyped.value); WriteTail(out, metric); } @@ -123,12 +113,12 @@ void SerializeHistogram(std::ostream& out, const MetricFamily& family, WriteTail(out, metric); WriteHead(out, family, metric, "_sum"); - out << ToString(hist.sample_sum); + WriteValue(out, hist.sample_sum); WriteTail(out, metric); double last = -std::numeric_limits::infinity(); for (auto& b : hist.bucket) { - WriteHead(out, family, metric, "_bucket", "le", ToString(b.upper_bound)); + WriteHead(out, family, metric, "_bucket", "le", b.upper_bound); last = b.upper_bound; out << b.cumulative_count; WriteTail(out, metric); @@ -184,8 +174,11 @@ void SerializeFamily(std::ostream& out, const MetricFamily& family) { void TextSerializer::Serialize(std::ostream& out, const std::vector& metrics) const { + std::locale saved_locale = out.getloc(); + out.imbue(std::locale::classic()); for (auto& family : metrics) { SerializeFamily(out, family); } + out.imbue(saved_locale); } } // namespace prometheus diff --git a/core/tests/CMakeLists.txt b/core/tests/CMakeLists.txt index ee94919b..cd220cb8 100644 --- a/core/tests/CMakeLists.txt +++ b/core/tests/CMakeLists.txt @@ -7,6 +7,7 @@ add_executable(prometheus_test gauge_test.cc histogram_test.cc registry_test.cc + serializer_test.cc summary_test.cc utils_test.cc ) diff --git a/core/tests/serializer_test.cc b/core/tests/serializer_test.cc new file mode 100644 index 00000000..4e915306 --- /dev/null +++ b/core/tests/serializer_test.cc @@ -0,0 +1,60 @@ +#include "prometheus/counter.h" +#include "prometheus/family.h" +#include "prometheus/text_serializer.h" + +#include +#include +#include + +namespace prometheus { +namespace { + +class SerializerTest : public testing::Test { + public: + void SetUp() override { + Family family{"requests_total", "", {}}; + auto& counter = family.Add({}); + counter.Increment(); + + collected = family.Collect(); + } + + std::vector collected; + TextSerializer textSerializer; +}; + +TEST_F(SerializerTest, shouldSerializeLocaleIndependent) { + // save and change locale + const std::locale oldLocale = std::locale::classic(); + std::locale::global(std::locale("de_DE.UTF-8")); + + const auto serialized = textSerializer.Serialize(collected); + EXPECT_THAT(serialized, testing::HasSubstr("1.0")); + + // restore locale + std::locale::global(oldLocale); +} + +TEST_F(SerializerTest, shouldRestoreStreamState) { + std::ostringstream os; + + // save stream state + auto saved_flags = os.flags(); + auto saved_precision = os.precision(); + auto saved_width = os.width(); + auto saved_fill = os.fill(); + auto saved_locale = os.getloc(); + + // serialize + textSerializer.Serialize(os, collected); + + // check for expected flags + EXPECT_EQ(os.flags(), saved_flags); + EXPECT_EQ(os.precision(), saved_precision); + EXPECT_EQ(os.width(), saved_width); + EXPECT_EQ(os.fill(), saved_fill); + EXPECT_EQ(os.getloc(), saved_locale); +} + +} // namespace +} // namespace prometheus From 396a72d3b4e5bce3eba596ead0ab949bc827e51a Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Mon, 1 Jul 2019 17:57:48 +0200 Subject: [PATCH 018/206] Fix Telegraf scrape test --- .travis.yml | 2 +- pull/tests/integration/scrape.conf | 2 ++ pull/tests/integration/scrape.sh | 26 ++++++++------------------ 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/.travis.yml b/.travis.yml index a3b4d522..9e523537 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,7 +44,7 @@ addons: script: - bazel build //... - bazel test --test_output=all //core/... //pull/... -# - bazel test --test_output=all //pull/tests/integration:scrape-test + - bazel test --test_output=all //pull/tests/integration:scrape-test # - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then bazel test --test_output=all //pull/tests/integration:lint-test; fi - bazel run -c opt //core/benchmarks diff --git a/pull/tests/integration/scrape.conf b/pull/tests/integration/scrape.conf index 2acc7be5..a9581256 100644 --- a/pull/tests/integration/scrape.conf +++ b/pull/tests/integration/scrape.conf @@ -1,5 +1,7 @@ [[inputs.prometheus]] # An array of urls to scrape metrics from. urls = ["http://localhost:8080/metrics"] + interval = '1s' [[outputs.file]] files = ["stdout"] + flush_interval = "1s" diff --git a/pull/tests/integration/scrape.sh b/pull/tests/integration/scrape.sh index 800b2513..a91f233e 100755 --- a/pull/tests/integration/scrape.sh +++ b/pull/tests/integration/scrape.sh @@ -6,24 +6,14 @@ if [ ! -x "$telegraf" ] ; then exit 1 fi -pull/tests/integration/sample-server& -sample_server_pid=$! -sleep 1 -telegraf_output="$(telegraf -test -config pull/tests/integration/scrape.conf)" -telegraf_run_result=$? -kill -9 $sample_server_pid +function timeout_after +{ + ( echo failing after $1 seconds for execution && sleep $1 && kill $$ ) & +} -if [ $telegraf_run_result -ne 0 ] ; then - exit $telegraf_run_result -fi - -if [[ ! $telegraf_output == *"time_running_seconds_total"* ]] ; then - echo "Could not find time_running_seconds_total in exposed metrics:" - echo "${telegraf_run_output}" - exit 1 -fi +trap 'kill $(jobs -p)' EXIT -echo "Success:" -echo "${telegraf_output}" +timeout_after 10 -exit 0 +pull/tests/integration/sample-server & +telegraf --config pull/tests/integration/scrape.conf --quiet | grep -m1 time_running_seconds_total From 7fcba1fcbfbdddd6bbd1f34e7d7cb059088371b6 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Wed, 3 Jul 2019 20:35:20 +0200 Subject: [PATCH 019/206] core: Move elememts from one vector to the final one --- core/src/registry.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/src/registry.cc b/core/src/registry.cc index ab19cfa6..24627679 100644 --- a/core/src/registry.cc +++ b/core/src/registry.cc @@ -1,5 +1,7 @@ #include "prometheus/registry.h" +#include + namespace prometheus { std::vector Registry::Collect() { @@ -7,7 +9,8 @@ std::vector Registry::Collect() { auto results = std::vector{}; for (auto&& collectable : collectables_) { auto metrics = collectable->Collect(); - results.insert(results.end(), metrics.begin(), metrics.end()); + results.insert(results.end(), std::make_move_iterator(metrics.begin()), + std::make_move_iterator(metrics.end())); } return results; From 00d1c4cc95a5c02164d73c702c5e2b9a87e7aa23 Mon Sep 17 00:00:00 2001 From: David Ray Date: Fri, 2 Aug 2019 16:30:57 +0100 Subject: [PATCH 020/206] Allow more than 1 histogram observation at a time Added the ObserveMultiple method to the Histogram. This is useful if you have already have values sorted into buckets, and the sum of the values but no longer have the individual values. --- core/include/prometheus/histogram.h | 10 +++++++++- core/src/histogram.cc | 9 +++++++++ core/tests/histogram_test.cc | 22 ++++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/core/include/prometheus/histogram.h b/core/include/prometheus/histogram.h index a7078747..845a2416 100644 --- a/core/include/prometheus/histogram.h +++ b/core/include/prometheus/histogram.h @@ -31,7 +31,7 @@ class Histogram { static const MetricType metric_type{MetricType::Histogram}; - /// \brief Create a histogram with manually choosen buckets. + /// \brief Create a histogram with manually chosen buckets. /// /// The BucketBoundaries are a list of monotonically increasing values /// representing the bucket boundaries. Each consecutive pair of values is @@ -51,6 +51,14 @@ class Histogram { /// sum of all observations is incremented. void Observe(double value); + /// \brief Observe multiple data points. + /// + /// Increments counters given a count for each bucket. (i.e. the caller of + /// this function must have already sorted the values into buckets). + /// Also increments the total sum of all observations by the given value. + void ObserveMultiple(const std::vector bucket_increments, + const double sum_of_values); + /// \brief Get the current value of the counter. /// /// Collect is called by the Registry when collecting metrics. diff --git a/core/src/histogram.cc b/core/src/histogram.cc index dce8c0ac..7c78bcc9 100644 --- a/core/src/histogram.cc +++ b/core/src/histogram.cc @@ -24,6 +24,15 @@ void Histogram::Observe(const double value) { bucket_counts_[bucket_index].Increment(); } +void Histogram::ObserveMultiple(const std::vector bucket_increments, + const double sum_of_values) { + sum_.Increment(sum_of_values); + + for (std::size_t i{0}; i < bucket_counts_.size(); ++i) { + { bucket_counts_[i].Increment(bucket_increments[i]); } + } +} + ClientMetric Histogram::Collect() const { auto metric = ClientMetric{}; diff --git a/core/tests/histogram_test.cc b/core/tests/histogram_test.cc index 60aa75fb..bb236de6 100644 --- a/core/tests/histogram_test.cc +++ b/core/tests/histogram_test.cc @@ -79,5 +79,27 @@ TEST(HistogramTest, cumulative_bucket_count) { EXPECT_EQ(h.bucket.at(2).cumulative_count, 7U); } +TEST(HistogramTest, observe_multiple_test_bucket_counts) { + Histogram histogram{{1, 2}}; + histogram.ObserveMultiple({5, 9, 3}, 20); + histogram.ObserveMultiple({0, 20, 6}, 34); + auto metric = histogram.Collect(); + auto h = metric.histogram; + ASSERT_EQ(h.bucket.size(), 3U); + EXPECT_EQ(h.bucket.at(0).cumulative_count, 5U); + EXPECT_EQ(h.bucket.at(1).cumulative_count, 34U); + EXPECT_EQ(h.bucket.at(2).cumulative_count, 43U); +} + +TEST(HistogramTest, observe_multiple_test_total_sum) { + Histogram histogram{{1, 2}}; + histogram.ObserveMultiple({5, 9, 3}, 20); + histogram.ObserveMultiple({0, 20, 6}, 34); + auto metric = histogram.Collect(); + auto h = metric.histogram; + EXPECT_EQ(h.sample_count, 43U); + EXPECT_EQ(h.sample_sum, 54); +} + } // namespace } // namespace prometheus From 0b34b87244d8c975d46a09360a40de9a32f8518b Mon Sep 17 00:00:00 2001 From: mkenigs <40775676+mkenigs@users.noreply.github.com> Date: Mon, 5 Aug 2019 23:40:52 -0700 Subject: [PATCH 021/206] typo: lable to label --- core/include/prometheus/family.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/include/prometheus/family.h b/core/include/prometheus/family.h index f3ed380b..7ec7bf57 100644 --- a/core/include/prometheus/family.h +++ b/core/include/prometheus/family.h @@ -100,12 +100,12 @@ class Family : public Collectable { /// http_requests_total{job= "prometheus",method= "POST"} /// /// \param labels Assign a set of key-value pairs (= labels) to the - /// dimensional data. The function does nothing, if the same set of lables + /// dimensional data. The function does nothing, if the same set of labels /// already exists. /// \param args Arguments are passed to the constructor of metric type T. See /// Counter, Gauge, Histogram or Summary for required constructor arguments. /// \return Return the newly created dimensional data or - if a same set of - /// lables already exists - the already existing dimensional data. + /// labels already exists - the already existing dimensional data. template T& Add(const std::map& labels, Args&&... args); From 1b5cf25e10d83be4061c5b322cf7224f17ccbbb8 Mon Sep 17 00:00:00 2001 From: matthew Date: Wed, 7 Aug 2019 22:12:47 -0700 Subject: [PATCH 022/206] CMake --- core/CMakeLists.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index f520ceec..38fdcca9 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -3,10 +3,6 @@ add_library(core src/check_names.cc src/counter.cc src/detail/ckms_quantiles.cc - src/detail/counter_builder.cc - src/detail/gauge_builder.cc - src/detail/histogram_builder.cc - src/detail/summary_builder.cc src/detail/time_window_quantiles.cc src/detail/utils.cc src/gauge.cc From 32cfada5abeca73aa37063afd3d97bbc60d46836 Mon Sep 17 00:00:00 2001 From: matthew Date: Wed, 7 Aug 2019 22:13:30 -0700 Subject: [PATCH 023/206] delete builders --- .../prometheus/detail/counter_builder.h | 29 ------------------- .../include/prometheus/detail/gauge_builder.h | 29 ------------------- .../prometheus/detail/histogram_builder.h | 29 ------------------- .../prometheus/detail/summary_builder.h | 29 ------------------- core/src/detail/counter_builder.cc | 29 ------------------- core/src/detail/gauge_builder.cc | 29 ------------------- core/src/detail/histogram_builder.cc | 29 ------------------- core/src/detail/summary_builder.cc | 29 ------------------- 8 files changed, 232 deletions(-) delete mode 100644 core/include/prometheus/detail/counter_builder.h delete mode 100644 core/include/prometheus/detail/gauge_builder.h delete mode 100644 core/include/prometheus/detail/histogram_builder.h delete mode 100644 core/include/prometheus/detail/summary_builder.h delete mode 100644 core/src/detail/counter_builder.cc delete mode 100644 core/src/detail/gauge_builder.cc delete mode 100644 core/src/detail/histogram_builder.cc delete mode 100644 core/src/detail/summary_builder.cc diff --git a/core/include/prometheus/detail/counter_builder.h b/core/include/prometheus/detail/counter_builder.h deleted file mode 100644 index 5967a7c5..00000000 --- a/core/include/prometheus/detail/counter_builder.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include -#include - -namespace prometheus { - -template -class Family; -class Counter; -class Registry; - -namespace detail { - -class CounterBuilder { - public: - CounterBuilder& Labels(const std::map& labels); - CounterBuilder& Name(const std::string&); - CounterBuilder& Help(const std::string&); - Family& Register(Registry&); - - private: - std::map labels_; - std::string name_; - std::string help_; -}; - -} // namespace detail -} // namespace prometheus diff --git a/core/include/prometheus/detail/gauge_builder.h b/core/include/prometheus/detail/gauge_builder.h deleted file mode 100644 index 2778ff85..00000000 --- a/core/include/prometheus/detail/gauge_builder.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include -#include - -namespace prometheus { - -template -class Family; -class Gauge; -class Registry; - -namespace detail { - -class GaugeBuilder { - public: - GaugeBuilder& Labels(const std::map& labels); - GaugeBuilder& Name(const std::string&); - GaugeBuilder& Help(const std::string&); - Family& Register(Registry&); - - private: - std::map labels_; - std::string name_; - std::string help_; -}; - -} // namespace detail -} // namespace prometheus diff --git a/core/include/prometheus/detail/histogram_builder.h b/core/include/prometheus/detail/histogram_builder.h deleted file mode 100644 index c2d9a1e4..00000000 --- a/core/include/prometheus/detail/histogram_builder.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include -#include - -namespace prometheus { - -template -class Family; -class Histogram; -class Registry; - -namespace detail { - -class HistogramBuilder { - public: - HistogramBuilder& Labels(const std::map& labels); - HistogramBuilder& Name(const std::string&); - HistogramBuilder& Help(const std::string&); - Family& Register(Registry&); - - private: - std::map labels_; - std::string name_; - std::string help_; -}; - -} // namespace detail -} // namespace prometheus diff --git a/core/include/prometheus/detail/summary_builder.h b/core/include/prometheus/detail/summary_builder.h deleted file mode 100644 index 1b8efa32..00000000 --- a/core/include/prometheus/detail/summary_builder.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include -#include - -namespace prometheus { - -template -class Family; -class Summary; -class Registry; - -namespace detail { - -class SummaryBuilder { - public: - SummaryBuilder& Labels(const std::map& labels); - SummaryBuilder& Name(const std::string&); - SummaryBuilder& Help(const std::string&); - Family& Register(Registry&); - - private: - std::map labels_; - std::string name_; - std::string help_; -}; - -} // namespace detail -} // namespace prometheus diff --git a/core/src/detail/counter_builder.cc b/core/src/detail/counter_builder.cc deleted file mode 100644 index 970b3def..00000000 --- a/core/src/detail/counter_builder.cc +++ /dev/null @@ -1,29 +0,0 @@ -#include "prometheus/detail/counter_builder.h" - -#include "prometheus/registry.h" - -namespace prometheus { -namespace detail { - -CounterBuilder& CounterBuilder::Labels( - const std::map& labels) { - labels_ = labels; - return *this; -} - -CounterBuilder& CounterBuilder::Name(const std::string& name) { - name_ = name; - return *this; -} - -CounterBuilder& CounterBuilder::Help(const std::string& help) { - help_ = help; - return *this; -} - -Family& CounterBuilder::Register(Registry& registry) { - return registry.Add(name_, help_, labels_); -} - -} // namespace detail -} // namespace prometheus diff --git a/core/src/detail/gauge_builder.cc b/core/src/detail/gauge_builder.cc deleted file mode 100644 index 20e37b16..00000000 --- a/core/src/detail/gauge_builder.cc +++ /dev/null @@ -1,29 +0,0 @@ -#include "prometheus/detail/gauge_builder.h" - -#include "prometheus/registry.h" - -namespace prometheus { -namespace detail { - -GaugeBuilder& GaugeBuilder::Labels( - const std::map& labels) { - labels_ = labels; - return *this; -} - -GaugeBuilder& GaugeBuilder::Name(const std::string& name) { - name_ = name; - return *this; -} - -GaugeBuilder& GaugeBuilder::Help(const std::string& help) { - help_ = help; - return *this; -} - -Family& GaugeBuilder::Register(Registry& registry) { - return registry.Add(name_, help_, labels_); -} - -} // namespace detail -} // namespace prometheus diff --git a/core/src/detail/histogram_builder.cc b/core/src/detail/histogram_builder.cc deleted file mode 100644 index c038e8ce..00000000 --- a/core/src/detail/histogram_builder.cc +++ /dev/null @@ -1,29 +0,0 @@ -#include "prometheus/detail/histogram_builder.h" - -#include "prometheus/registry.h" - -namespace prometheus { -namespace detail { - -HistogramBuilder& HistogramBuilder::Labels( - const std::map& labels) { - labels_ = labels; - return *this; -} - -HistogramBuilder& HistogramBuilder::Name(const std::string& name) { - name_ = name; - return *this; -} - -HistogramBuilder& HistogramBuilder::Help(const std::string& help) { - help_ = help; - return *this; -} - -Family& HistogramBuilder::Register(Registry& registry) { - return registry.Add(name_, help_, labels_); -} - -} // namespace detail -} // namespace prometheus diff --git a/core/src/detail/summary_builder.cc b/core/src/detail/summary_builder.cc deleted file mode 100644 index 20a3c70b..00000000 --- a/core/src/detail/summary_builder.cc +++ /dev/null @@ -1,29 +0,0 @@ -#include "prometheus/detail/summary_builder.h" - -#include "prometheus/registry.h" - -namespace prometheus { -namespace detail { - -SummaryBuilder& SummaryBuilder::Labels( - const std::map& labels) { - labels_ = labels; - return *this; -} - -SummaryBuilder& SummaryBuilder::Name(const std::string& name) { - name_ = name; - return *this; -} - -SummaryBuilder& SummaryBuilder::Help(const std::string& help) { - help_ = help; - return *this; -} - -Family& SummaryBuilder::Register(Registry& registry) { - return registry.Add(name_, help_, labels_); -} - -} // namespace detail -} // namespace prometheus From 6d47a30b1005ab25846f3052ce487b0e5ac01548 Mon Sep 17 00:00:00 2001 From: matthew Date: Wed, 7 Aug 2019 22:15:55 -0700 Subject: [PATCH 024/206] use templatized builder --- core/include/prometheus/counter.h | 4 ++-- core/include/prometheus/gauge.h | 4 ++-- core/include/prometheus/histogram.h | 4 ++-- core/include/prometheus/summary.h | 4 ++-- core/src/counter.cc | 2 +- core/src/gauge.cc | 2 +- core/src/histogram.cc | 2 +- core/src/summary.cc | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/core/include/prometheus/counter.h b/core/include/prometheus/counter.h index 3faf693c..04df709a 100644 --- a/core/include/prometheus/counter.h +++ b/core/include/prometheus/counter.h @@ -1,7 +1,7 @@ #pragma once #include "prometheus/client_metric.h" -#include "prometheus/detail/counter_builder.h" +#include "prometheus/detail/builder.h" #include "prometheus/gauge.h" #include "prometheus/metric_type.h" @@ -76,6 +76,6 @@ class Counter { /// /// To finish the configuration of the Counter metric, register it with /// Register(Registry&). -detail::CounterBuilder BuildCounter(); +detail::Builder BuildCounter(); } // namespace prometheus diff --git a/core/include/prometheus/gauge.h b/core/include/prometheus/gauge.h index 8184aa67..7d2f2f38 100644 --- a/core/include/prometheus/gauge.h +++ b/core/include/prometheus/gauge.h @@ -3,7 +3,7 @@ #include #include "prometheus/client_metric.h" -#include "prometheus/detail/gauge_builder.h" +#include "prometheus/detail/builder.h" #include "prometheus/metric_type.h" namespace prometheus { @@ -88,6 +88,6 @@ class Gauge { /// /// To finish the configuration of the Gauge metric register it with /// Register(Registry&). -detail::GaugeBuilder BuildGauge(); +detail::Builder BuildGauge(); } // namespace prometheus diff --git a/core/include/prometheus/histogram.h b/core/include/prometheus/histogram.h index a7078747..f68ec49c 100644 --- a/core/include/prometheus/histogram.h +++ b/core/include/prometheus/histogram.h @@ -4,7 +4,7 @@ #include "prometheus/client_metric.h" #include "prometheus/counter.h" -#include "prometheus/detail/histogram_builder.h" +#include "prometheus/detail/builder.h" #include "prometheus/metric_type.h" namespace prometheus { @@ -89,6 +89,6 @@ class Histogram { /// /// To finish the configuration of the Histogram metric register it with /// Register(Registry&). -detail::HistogramBuilder BuildHistogram(); +detail::Builder BuildHistogram(); } // namespace prometheus diff --git a/core/include/prometheus/summary.h b/core/include/prometheus/summary.h index 56fcd0a8..b9eb9550 100644 --- a/core/include/prometheus/summary.h +++ b/core/include/prometheus/summary.h @@ -7,7 +7,7 @@ #include "prometheus/client_metric.h" #include "prometheus/detail/ckms_quantiles.h" -#include "prometheus/detail/summary_builder.h" +#include "prometheus/detail/builder.h" #include "prometheus/detail/time_window_quantiles.h" #include "prometheus/metric_type.h" @@ -117,6 +117,6 @@ class Summary { /// /// To finish the configuration of the Summary metric register it with /// Register(Registry&). -detail::SummaryBuilder BuildSummary(); +detail::Builder BuildSummary(); } // namespace prometheus diff --git a/core/src/counter.cc b/core/src/counter.cc index db2824d9..4506c114 100644 --- a/core/src/counter.cc +++ b/core/src/counter.cc @@ -14,6 +14,6 @@ ClientMetric Counter::Collect() const { return metric; } -detail::CounterBuilder BuildCounter() { return {}; } +detail::Builder BuildCounter() { return {}; } } // namespace prometheus diff --git a/core/src/gauge.cc b/core/src/gauge.cc index 129b6679..2b790b57 100644 --- a/core/src/gauge.cc +++ b/core/src/gauge.cc @@ -45,6 +45,6 @@ ClientMetric Gauge::Collect() const { return metric; } -detail::GaugeBuilder BuildGauge() { return {}; } +detail::Builder BuildGauge() { return {}; } } // namespace prometheus diff --git a/core/src/histogram.cc b/core/src/histogram.cc index dce8c0ac..807e24fc 100644 --- a/core/src/histogram.cc +++ b/core/src/histogram.cc @@ -43,6 +43,6 @@ ClientMetric Histogram::Collect() const { return metric; } -detail::HistogramBuilder BuildHistogram() { return {}; } +detail::Builder BuildHistogram() { return {}; } } // namespace prometheus diff --git a/core/src/summary.cc b/core/src/summary.cc index c81db508..4065a27d 100644 --- a/core/src/summary.cc +++ b/core/src/summary.cc @@ -34,6 +34,6 @@ ClientMetric Summary::Collect() { return metric; } -detail::SummaryBuilder BuildSummary() { return {}; } +detail::Builder BuildSummary() { return {}; } } // namespace prometheus From 35d46a57122ff0b0bb1677af3e08c944c90fc043 Mon Sep 17 00:00:00 2001 From: matthew Date: Wed, 7 Aug 2019 22:18:59 -0700 Subject: [PATCH 025/206] forward declarations and use templatized --- core/include/prometheus/registry.h | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/core/include/prometheus/registry.h b/core/include/prometheus/registry.h index cc901073..4be5e7dc 100644 --- a/core/include/prometheus/registry.h +++ b/core/include/prometheus/registry.h @@ -7,20 +7,18 @@ #include #include "prometheus/collectable.h" -#include "prometheus/counter.h" -#include "prometheus/detail/counter_builder.h" #include "prometheus/detail/future_std.h" -#include "prometheus/detail/gauge_builder.h" -#include "prometheus/detail/histogram_builder.h" -#include "prometheus/detail/summary_builder.h" #include "prometheus/family.h" -#include "prometheus/gauge.h" -#include "prometheus/histogram.h" #include "prometheus/metric_family.h" -#include "prometheus/summary.h" namespace prometheus { +namespace detail { + +template +class Builder; + +} /// \brief Manages the collection of a number of metrics. /// /// The Registry is responsible to expose data to a class/method/function @@ -45,10 +43,8 @@ class Registry : public Collectable { std::vector Collect() override; private: - friend class detail::CounterBuilder; - friend class detail::GaugeBuilder; - friend class detail::HistogramBuilder; - friend class detail::SummaryBuilder; + template + friend class detail::Builder; template Family& Add(const std::string& name, const std::string& help, From a1963aaa2f0b220263dc6b6f24f180d03e25a12d Mon Sep 17 00:00:00 2001 From: matthew Date: Wed, 7 Aug 2019 22:21:32 -0700 Subject: [PATCH 026/206] builder --- core/include/prometheus/detail/builder.h | 54 ++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 core/include/prometheus/detail/builder.h diff --git a/core/include/prometheus/detail/builder.h b/core/include/prometheus/detail/builder.h new file mode 100644 index 00000000..91219b65 --- /dev/null +++ b/core/include/prometheus/detail/builder.h @@ -0,0 +1,54 @@ +#pragma once + +#include +#include + +#include "prometheus/registry.h" + +namespace prometheus { + +template +class Family; + +namespace detail { + +template +class Builder { + public: + Builder& Labels(const std::map& labels); + Builder& Name(const std::string&); + Builder& Help(const std::string&); + Family& Register(Registry&); + + private: + std::map labels_; + std::string name_; + std::string help_; +}; + +template +Builder& Builder::Labels( + const std::map& labels) { + labels_ = labels; + return *this; +} + +template +Builder& Builder::Name(const std::string& name) { + name_ = name; + return *this; +} + +template +Builder& Builder::Help(const std::string& help) { + help_ = help; + return *this; +} + +template +Family& Builder::Register(Registry& registry) { + return registry.Add(name_, help_, labels_); +} + +} // namespace detail +} // namespace prometheus \ No newline at end of file From a34ead70271a28f307fcaf511c267d098ec839a8 Mon Sep 17 00:00:00 2001 From: matthew Date: Wed, 7 Aug 2019 22:28:11 -0700 Subject: [PATCH 027/206] include fixes --- core/tests/registry_test.cc | 2 ++ pull/src/handler.cc | 2 ++ pull/src/handler.h | 2 ++ pull/tests/integration/sample_server.cc | 1 + push/tests/integration/sample_client.cc | 1 + 5 files changed, 8 insertions(+) diff --git a/core/tests/registry_test.cc b/core/tests/registry_test.cc index 6c6ecc68..652f54bc 100644 --- a/core/tests/registry_test.cc +++ b/core/tests/registry_test.cc @@ -1,3 +1,5 @@ +#include "prometheus/counter.h" +#include "prometheus/histogram.h" #include "prometheus/registry.h" #include diff --git a/pull/src/handler.cc b/pull/src/handler.cc index d2efca8a..ea94365a 100644 --- a/pull/src/handler.cc +++ b/pull/src/handler.cc @@ -1,4 +1,6 @@ #include "handler.h" +#include "prometheus/counter.h" +#include "prometheus/summary.h" #include #include diff --git a/pull/src/handler.h b/pull/src/handler.h index 70c29a24..112267aa 100644 --- a/pull/src/handler.h +++ b/pull/src/handler.h @@ -4,7 +4,9 @@ #include #include "CivetServer.h" +#include "prometheus/counter.h" #include "prometheus/registry.h" +#include "prometheus/summary.h" namespace prometheus { namespace detail { diff --git a/pull/tests/integration/sample_server.cc b/pull/tests/integration/sample_server.cc index 0ca20ebf..ab8c3df8 100644 --- a/pull/tests/integration/sample_server.cc +++ b/pull/tests/integration/sample_server.cc @@ -4,6 +4,7 @@ #include #include +#include #include #include diff --git a/push/tests/integration/sample_client.cc b/push/tests/integration/sample_client.cc index abad8e87..84a6c79d 100644 --- a/push/tests/integration/sample_client.cc +++ b/push/tests/integration/sample_client.cc @@ -5,6 +5,7 @@ #include #include +#include #include #include From 2865d2f6c1aa6fea4fcb1f4aa105f3b982fec1be Mon Sep 17 00:00:00 2001 From: mkenigs Date: Thu, 8 Aug 2019 10:45:01 -0700 Subject: [PATCH 028/206] benchmark includes --- core/benchmarks/counter_bench.cc | 1 + core/benchmarks/gauge_bench.cc | 1 + core/benchmarks/histogram_bench.cc | 1 + core/benchmarks/registry_bench.cc | 1 + core/benchmarks/summary_bench.cc | 1 + 5 files changed, 5 insertions(+) diff --git a/core/benchmarks/counter_bench.cc b/core/benchmarks/counter_bench.cc index 34707ac5..3bae0557 100644 --- a/core/benchmarks/counter_bench.cc +++ b/core/benchmarks/counter_bench.cc @@ -1,4 +1,5 @@ #include +#include #include static void BM_Counter_Increment(benchmark::State& state) { diff --git a/core/benchmarks/gauge_bench.cc b/core/benchmarks/gauge_bench.cc index a7aaeb2c..d5afc492 100644 --- a/core/benchmarks/gauge_bench.cc +++ b/core/benchmarks/gauge_bench.cc @@ -1,4 +1,5 @@ #include +#include #include static void BM_Gauge_Increment(benchmark::State& state) { diff --git a/core/benchmarks/histogram_bench.cc b/core/benchmarks/histogram_bench.cc index 4926075d..5f48971c 100644 --- a/core/benchmarks/histogram_bench.cc +++ b/core/benchmarks/histogram_bench.cc @@ -2,6 +2,7 @@ #include #include +#include #include using prometheus::Histogram; diff --git a/core/benchmarks/registry_bench.cc b/core/benchmarks/registry_bench.cc index ad81432d..ea74ef24 100644 --- a/core/benchmarks/registry_bench.cc +++ b/core/benchmarks/registry_bench.cc @@ -1,6 +1,7 @@ #include #include +#include #include #include "benchmark_helpers.h" diff --git a/core/benchmarks/summary_bench.cc b/core/benchmarks/summary_bench.cc index 40917eee..95596002 100644 --- a/core/benchmarks/summary_bench.cc +++ b/core/benchmarks/summary_bench.cc @@ -2,6 +2,7 @@ #include #include +#include #include using prometheus::Summary; From eb6f1ab157b4382f8da730cbf9278b1182c46ebe Mon Sep 17 00:00:00 2001 From: David Ray Date: Wed, 14 Aug 2019 14:03:20 +0100 Subject: [PATCH 029/206] Fix Histogram::ObserveMultiple bug. Now throw length_error if the number of bucket increments is not equal to the number of buckets in the histogram. --- core/src/histogram.cc | 5 +++++ core/tests/histogram_test.cc | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/core/src/histogram.cc b/core/src/histogram.cc index 7c78bcc9..334aeda9 100644 --- a/core/src/histogram.cc +++ b/core/src/histogram.cc @@ -26,6 +26,11 @@ void Histogram::Observe(const double value) { void Histogram::ObserveMultiple(const std::vector bucket_increments, const double sum_of_values) { + if (bucket_increments.size() != bucket_counts_.size()) { + throw std::length_error("The size of bucket_increments was not equal to" + "the number of buckets in the histogram."); + } + sum_.Increment(sum_of_values); for (std::size_t i{0}; i < bucket_counts_.size(); ++i) { diff --git a/core/tests/histogram_test.cc b/core/tests/histogram_test.cc index bb236de6..23494edf 100644 --- a/core/tests/histogram_test.cc +++ b/core/tests/histogram_test.cc @@ -101,5 +101,13 @@ TEST(HistogramTest, observe_multiple_test_total_sum) { EXPECT_EQ(h.sample_sum, 54); } +TEST(HistogramTest, observe_multiple_test_length_error) { + Histogram histogram{{1, 2}}; + // 2 bucket boundaries means there are 3 buckets, so giving just 2 bucket + // increments should result in a length_error. + ASSERT_THROW(histogram.ObserveMultiple({5, 9}, 20), + std::length_error); +} + } // namespace } // namespace prometheus From df1a12b8bb1a8d62e9f25be1442019757dfc9bfa Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Fri, 16 Aug 2019 13:58:06 +0200 Subject: [PATCH 030/206] Fix build with MSVC and CMake 3.10 Fixes: #297 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 20d7190e..406e74f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,7 +35,7 @@ endif() # build flags for CI system -if(ENABLE_WARNINGS_AS_ERRORS) +if(ENABLE_WARNINGS_AS_ERRORS AND NOT MSVC) add_compile_options( $<$,CXX>,$>:-Werror> $<$,CXX>,$>:-Wall> From cd4728bb8f5f64020879667d301f0d264e32e419 Mon Sep 17 00:00:00 2001 From: michenicholas <32436082+michenicholas@users.noreply.github.com> Date: Mon, 26 Aug 2019 18:42:20 -0500 Subject: [PATCH 031/206] add include --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 1e0723f5..918262fb 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ See https://jupp0r.github.io/prometheus-cpp for more detailed interface document #include #include +#include #include #include From 1bf46d4e32851bc8e1eaa53cd7ca7796ffcc38d6 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 31 Aug 2019 12:05:36 +0200 Subject: [PATCH 032/206] core: hide builder, family, and registry implementation --- core/CMakeLists.txt | 3 + core/include/prometheus/detail/builder.h | 26 +------ core/include/prometheus/family.h | 88 ++---------------------- core/include/prometheus/registry.h | 10 --- core/src/counter.cc | 11 +++ core/src/detail/builder.impl.h | 35 ++++++++++ core/src/family.impl.h | 87 +++++++++++++++++++++++ core/src/gauge.cc | 11 +++ core/src/histogram.cc | 11 +++ core/src/registry.impl.h | 17 +++++ core/src/summary.cc | 11 +++ 11 files changed, 192 insertions(+), 118 deletions(-) create mode 100644 core/src/detail/builder.impl.h create mode 100644 core/src/family.impl.h create mode 100644 core/src/registry.impl.h diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 38fdcca9..b2a12caf 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -2,12 +2,15 @@ add_library(core src/check_names.cc src/counter.cc + src/detail/builder.impl.h src/detail/ckms_quantiles.cc src/detail/time_window_quantiles.cc src/detail/utils.cc src/gauge.cc + src/family.impl.h src/histogram.cc src/registry.cc + src/registry.impl.h src/serializer.cc src/summary.cc src/text_serializer.cc diff --git a/core/include/prometheus/detail/builder.h b/core/include/prometheus/detail/builder.h index 91219b65..e40a42f1 100644 --- a/core/include/prometheus/detail/builder.h +++ b/core/include/prometheus/detail/builder.h @@ -26,29 +26,5 @@ class Builder { std::string help_; }; -template -Builder& Builder::Labels( - const std::map& labels) { - labels_ = labels; - return *this; -} - -template -Builder& Builder::Name(const std::string& name) { - name_ = name; - return *this; -} - -template -Builder& Builder::Help(const std::string& help) { - help_ = help; - return *this; -} - -template -Family& Builder::Register(Registry& registry) { - return registry.Add(name_, help_, labels_); -} - } // namespace detail -} // namespace prometheus \ No newline at end of file +} // namespace prometheus diff --git a/core/include/prometheus/family.h b/core/include/prometheus/family.h index 7ec7bf57..39904fc4 100644 --- a/core/include/prometheus/family.h +++ b/core/include/prometheus/family.h @@ -107,7 +107,9 @@ class Family : public Collectable { /// \return Return the newly created dimensional data or - if a same set of /// labels already exists - the already existing dimensional data. template - T& Add(const std::map& labels, Args&&... args); + T& Add(const std::map& labels, Args&&... args) { + return Add(labels, detail::make_unique(args...)); + } /// \brief Remove the given dimensional data. /// @@ -133,88 +135,8 @@ class Family : public Collectable { std::mutex mutex_; ClientMetric CollectMetric(std::size_t hash, T* metric); + T& Add(const std::map& labels, + std::unique_ptr object); }; -template -Family::Family(const std::string& name, const std::string& help, - const std::map& constant_labels) - : name_(name), help_(help), constant_labels_(constant_labels) { - assert(CheckMetricName(name_)); -} - -template -template -T& Family::Add(const std::map& labels, - Args&&... args) { - auto hash = detail::hash_labels(labels); - std::lock_guard lock{mutex_}; - auto metrics_iter = metrics_.find(hash); - - if (metrics_iter != metrics_.end()) { -#ifndef NDEBUG - auto labels_iter = labels_.find(hash); - assert(labels_iter != labels_.end()); - const auto& old_labels = labels_iter->second; - assert(labels == old_labels); -#endif - return *metrics_iter->second; - } else { -#ifndef NDEBUG - for (auto& label_pair : labels) { - auto& label_name = label_pair.first; - assert(CheckLabelName(label_name)); - } -#endif - - auto metric = - metrics_.insert(std::make_pair(hash, detail::make_unique(args...))); - assert(metric.second); - labels_.insert({hash, labels}); - labels_reverse_lookup_.insert({metric.first->second.get(), hash}); - return *(metric.first->second); - } -} - -template -void Family::Remove(T* metric) { - std::lock_guard lock{mutex_}; - if (labels_reverse_lookup_.count(metric) == 0) { - return; - } - - auto hash = labels_reverse_lookup_.at(metric); - metrics_.erase(hash); - labels_.erase(hash); - labels_reverse_lookup_.erase(metric); -} - -template -std::vector Family::Collect() { - std::lock_guard lock{mutex_}; - auto family = MetricFamily{}; - family.name = name_; - family.help = help_; - family.type = T::metric_type; - for (const auto& m : metrics_) { - family.metric.push_back(std::move(CollectMetric(m.first, m.second.get()))); - } - return {family}; -} - -template -ClientMetric Family::CollectMetric(std::size_t hash, T* metric) { - auto collected = metric->Collect(); - auto add_label = - [&collected](const std::pair& label_pair) { - auto label = ClientMetric::Label{}; - label.name = label_pair.first; - label.value = label_pair.second; - collected.label.push_back(std::move(label)); - }; - std::for_each(constant_labels_.cbegin(), constant_labels_.cend(), add_label); - const auto& metric_labels = labels_.at(hash); - std::for_each(metric_labels.cbegin(), metric_labels.cend(), add_label); - return collected; -} - } // namespace prometheus diff --git a/core/include/prometheus/registry.h b/core/include/prometheus/registry.h index 4be5e7dc..ef15305a 100644 --- a/core/include/prometheus/registry.h +++ b/core/include/prometheus/registry.h @@ -54,14 +54,4 @@ class Registry : public Collectable { std::mutex mutex_; }; -template -Family& Registry::Add(const std::string& name, const std::string& help, - const std::map& labels) { - std::lock_guard lock{mutex_}; - auto family = detail::make_unique>(name, help, labels); - auto& ref = *family; - collectables_.push_back(std::move(family)); - return ref; -} - } // namespace prometheus diff --git a/core/src/counter.cc b/core/src/counter.cc index 4506c114..1b2c738c 100644 --- a/core/src/counter.cc +++ b/core/src/counter.cc @@ -1,5 +1,9 @@ #include "prometheus/counter.h" +#include "detail/builder.impl.h" +#include "family.impl.h" +#include "registry.impl.h" + namespace prometheus { void Counter::Increment() { gauge_.Increment(); } @@ -14,6 +18,13 @@ ClientMetric Counter::Collect() const { return metric; } +template class detail::Builder; +template class Family; + +template Family& Registry::Add( + const std::string& name, const std::string& help, + const std::map& labels); + detail::Builder BuildCounter() { return {}; } } // namespace prometheus diff --git a/core/src/detail/builder.impl.h b/core/src/detail/builder.impl.h new file mode 100644 index 00000000..82ff9591 --- /dev/null +++ b/core/src/detail/builder.impl.h @@ -0,0 +1,35 @@ +#pragma once + +#include "prometheus/detail/builder.h" + +namespace prometheus { + +namespace detail { + +template +Builder& Builder::Labels( + const std::map& labels) { + labels_ = labels; + return *this; +} + +template +Builder& Builder::Name(const std::string& name) { + name_ = name; + return *this; +} + +template +Builder& Builder::Help(const std::string& help) { + help_ = help; + return *this; +} + +template +Family& Builder::Register(Registry& registry) { + return registry.Add(name_, help_, labels_); +} + +} // namespace detail + +} // namespace prometheus diff --git a/core/src/family.impl.h b/core/src/family.impl.h new file mode 100644 index 00000000..0c1f07b8 --- /dev/null +++ b/core/src/family.impl.h @@ -0,0 +1,87 @@ +#pragma once + +#include "prometheus/family.h" + +namespace prometheus { + +template +Family::Family(const std::string& name, const std::string& help, + const std::map& constant_labels) + : name_(name), help_(help), constant_labels_(constant_labels) { + assert(CheckMetricName(name_)); +} + +template +T& Family::Add(const std::map& labels, + std::unique_ptr object) { + auto hash = detail::hash_labels(labels); + std::lock_guard lock{mutex_}; + auto metrics_iter = metrics_.find(hash); + + if (metrics_iter != metrics_.end()) { +#ifndef NDEBUG + auto labels_iter = labels_.find(hash); + assert(labels_iter != labels_.end()); + const auto& old_labels = labels_iter->second; + assert(labels == old_labels); +#endif + return *metrics_iter->second; + } else { +#ifndef NDEBUG + for (auto& label_pair : labels) { + auto& label_name = label_pair.first; + assert(CheckLabelName(label_name)); + } +#endif + + auto metric = metrics_.insert(std::make_pair(hash, std::move(object))); + assert(metric.second); + labels_.insert({hash, labels}); + labels_reverse_lookup_.insert({metric.first->second.get(), hash}); + return *(metric.first->second); + } +} + +template +void Family::Remove(T* metric) { + std::lock_guard lock{mutex_}; + if (labels_reverse_lookup_.count(metric) == 0) { + return; + } + + auto hash = labels_reverse_lookup_.at(metric); + metrics_.erase(hash); + labels_.erase(hash); + labels_reverse_lookup_.erase(metric); +} + +template +std::vector Family::Collect() { + std::lock_guard lock{mutex_}; + auto family = MetricFamily{}; + family.name = name_; + family.help = help_; + family.type = T::metric_type; + for (const auto& m : metrics_) { + family.metric.push_back(std::move(CollectMetric(m.first, m.second.get()))); + } + return {family}; +} + +template +ClientMetric Family::CollectMetric(std::size_t hash, T* metric) { + auto collected = metric->Collect(); + auto add_label = + [&collected](const std::pair& label_pair) { + auto label = ClientMetric::Label{}; + label.name = label_pair.first; + label.value = label_pair.second; + collected.label.push_back(std::move(label)); + }; + std::for_each(constant_labels_.cbegin(), constant_labels_.cend(), add_label); + const auto& metric_labels = labels_.at(hash); + std::for_each(metric_labels.cbegin(), metric_labels.cend(), add_label); + return collected; +} + +} // namespace prometheus diff --git a/core/src/gauge.cc b/core/src/gauge.cc index 2b790b57..7a000e7d 100644 --- a/core/src/gauge.cc +++ b/core/src/gauge.cc @@ -1,5 +1,9 @@ #include "prometheus/gauge.h" +#include "detail/builder.impl.h" +#include "family.impl.h" +#include "registry.impl.h" + #include namespace prometheus { @@ -45,6 +49,13 @@ ClientMetric Gauge::Collect() const { return metric; } +template class Family; +template class detail::Builder; + +template Family& Registry::Add( + const std::string& name, const std::string& help, + const std::map& labels); + detail::Builder BuildGauge() { return {}; } } // namespace prometheus diff --git a/core/src/histogram.cc b/core/src/histogram.cc index 5f853436..c059b136 100644 --- a/core/src/histogram.cc +++ b/core/src/histogram.cc @@ -1,5 +1,9 @@ #include "prometheus/histogram.h" +#include "detail/builder.impl.h" +#include "family.impl.h" +#include "registry.impl.h" + #include #include #include @@ -57,6 +61,13 @@ ClientMetric Histogram::Collect() const { return metric; } +template class Family; +template class detail::Builder; + +template Family& Registry::Add( + const std::string& name, const std::string& help, + const std::map& labels); + detail::Builder BuildHistogram() { return {}; } } // namespace prometheus diff --git a/core/src/registry.impl.h b/core/src/registry.impl.h new file mode 100644 index 00000000..353280e1 --- /dev/null +++ b/core/src/registry.impl.h @@ -0,0 +1,17 @@ +#pragma once + +#include "prometheus/registry.h" + +namespace prometheus { + +template +Family& Registry::Add(const std::string& name, const std::string& help, + const std::map& labels) { + std::lock_guard lock{mutex_}; + auto family = detail::make_unique>(name, help, labels); + auto& ref = *family; + collectables_.push_back(std::move(family)); + return ref; +} + +} // namespace prometheus diff --git a/core/src/summary.cc b/core/src/summary.cc index 4065a27d..cfc3fa0d 100644 --- a/core/src/summary.cc +++ b/core/src/summary.cc @@ -1,5 +1,9 @@ #include "prometheus/summary.h" +#include "detail/builder.impl.h" +#include "family.impl.h" +#include "registry.impl.h" + namespace prometheus { Summary::Summary(const Quantiles& quantiles, @@ -34,6 +38,13 @@ ClientMetric Summary::Collect() { return metric; } +template class Family; +template class detail::Builder; + +template Family& Registry::Add( + const std::string& name, const std::string& help, + const std::map& labels); + detail::Builder BuildSummary() { return {}; } } // namespace prometheus From 538ed3af0de319d61043f903ce60b7dba29e5a33 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 31 Aug 2019 18:21:11 +0200 Subject: [PATCH 033/206] Add (shared) library versioning Closes: #223 --- CMakeLists.txt | 10 +++++++++- core/CMakeLists.txt | 15 +++++++++++++-- core/include/prometheus/check_names.h | 6 ++++-- core/include/prometheus/client_metric.h | 4 +++- core/include/prometheus/collectable.h | 4 +++- core/include/prometheus/counter.h | 5 +++-- core/include/prometheus/detail/ckms_quantiles.h | 6 ++++-- .../prometheus/detail/time_window_quantiles.h | 3 ++- core/include/prometheus/detail/utils.h | 5 ++++- core/include/prometheus/family.h | 3 ++- core/include/prometheus/gauge.h | 5 +++-- core/include/prometheus/histogram.h | 5 +++-- core/include/prometheus/metric_family.h | 3 ++- core/include/prometheus/registry.h | 3 ++- core/include/prometheus/serializer.h | 3 ++- core/include/prometheus/summary.h | 5 +++-- core/include/prometheus/text_serializer.h | 3 ++- core/src/counter.cc | 4 ++-- core/src/gauge.cc | 4 ++-- core/src/histogram.cc | 4 ++-- core/src/summary.cc | 4 ++-- pull/CMakeLists.txt | 15 +++++++++++++-- pull/include/prometheus/exposer.h | 3 ++- push/CMakeLists.txt | 15 +++++++++++++-- push/include/prometheus/gateway.h | 3 ++- 25 files changed, 102 insertions(+), 38 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 406e74f2..980ee7e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,9 @@ cmake_minimum_required(VERSION 3.5 FATAL_ERROR) -project(prometheus-cpp) +project(prometheus-cpp VERSION 0.8.0) +include(GenerateExportHeader) include(GNUInstallDirs) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") @@ -20,6 +21,13 @@ if(OVERRIDE_CXX_STANDARD_FLAGS) set(CMAKE_CXX_EXTENSIONS Off) endif() +# Hide things by default for shared libraries +if(BUILD_SHARED_LIBS) + set(CMAKE_C_VISIBILITY_PRESET hidden) + set(CMAKE_CXX_VISIBILITY_PRESET hidden) + set(CMAKE_VISIBILITY_INLINES_HIDDEN YES) +endif() + set(CMAKE_THREAD_PREFER_PTHREAD TRUE) find_package(Threads) diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index b2a12caf..619672ea 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -18,6 +18,11 @@ add_library(core add_library(${PROJECT_NAME}::core ALIAS core) +generate_export_header(core + EXPORT_FILE_NAME include/prometheus/detail/core_export.h + PREFIX_NAME PROMETHEUS_CPP_ +) + target_link_libraries(core PRIVATE Threads::Threads @@ -27,9 +32,15 @@ target_link_libraries(core target_include_directories(core PUBLIC $ + $ ) -set_target_properties(core PROPERTIES OUTPUT_NAME ${PROJECT_NAME}-core) +set_target_properties(core + PROPERTIES + OUTPUT_NAME ${PROJECT_NAME}-core + VERSION "${PROJECT_VERSION}" + SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}" +) install( TARGETS core @@ -41,7 +52,7 @@ install( ) install( - DIRECTORY include/ + DIRECTORY include/ ${CMAKE_CURRENT_BINARY_DIR}/include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) diff --git a/core/include/prometheus/check_names.h b/core/include/prometheus/check_names.h index 91acf239..2d73ab6c 100644 --- a/core/include/prometheus/check_names.h +++ b/core/include/prometheus/check_names.h @@ -2,8 +2,10 @@ #include +#include "prometheus/detail/core_export.h" + namespace prometheus { -bool CheckMetricName(const std::string& name); -bool CheckLabelName(const std::string& name); +PROMETHEUS_CPP_CORE_EXPORT bool CheckMetricName(const std::string& name); +PROMETHEUS_CPP_CORE_EXPORT bool CheckLabelName(const std::string& name); } // namespace prometheus diff --git a/core/include/prometheus/client_metric.h b/core/include/prometheus/client_metric.h index 4f04281a..b224b80c 100644 --- a/core/include/prometheus/client_metric.h +++ b/core/include/prometheus/client_metric.h @@ -5,9 +5,11 @@ #include #include +#include "prometheus/detail/core_export.h" + namespace prometheus { -struct ClientMetric { +struct PROMETHEUS_CPP_CORE_EXPORT ClientMetric { // Label struct Label { diff --git a/core/include/prometheus/collectable.h b/core/include/prometheus/collectable.h index 97ce02ab..aaf1dce9 100644 --- a/core/include/prometheus/collectable.h +++ b/core/include/prometheus/collectable.h @@ -2,6 +2,8 @@ #include +#include "prometheus/detail/core_export.h" + namespace prometheus { struct MetricFamily; } @@ -12,7 +14,7 @@ namespace prometheus { /// collect metrics. /// /// A Collectable has to be registered for collection. See Registry. -class Collectable { +class PROMETHEUS_CPP_CORE_EXPORT Collectable { public: virtual ~Collectable() = default; diff --git a/core/include/prometheus/counter.h b/core/include/prometheus/counter.h index 04df709a..6ec01dd8 100644 --- a/core/include/prometheus/counter.h +++ b/core/include/prometheus/counter.h @@ -2,6 +2,7 @@ #include "prometheus/client_metric.h" #include "prometheus/detail/builder.h" +#include "prometheus/detail/core_export.h" #include "prometheus/gauge.h" #include "prometheus/metric_type.h" @@ -22,7 +23,7 @@ namespace prometheus { /// /// The class is thread-safe. No concurrent call to any API of this type causes /// a data race. -class Counter { +class PROMETHEUS_CPP_CORE_EXPORT Counter { public: static const MetricType metric_type{MetricType::Counter}; @@ -76,6 +77,6 @@ class Counter { /// /// To finish the configuration of the Counter metric, register it with /// Register(Registry&). -detail::Builder BuildCounter(); +PROMETHEUS_CPP_CORE_EXPORT detail::Builder BuildCounter(); } // namespace prometheus diff --git a/core/include/prometheus/detail/ckms_quantiles.h b/core/include/prometheus/detail/ckms_quantiles.h index 2fe6fe22..da0950fc 100644 --- a/core/include/prometheus/detail/ckms_quantiles.h +++ b/core/include/prometheus/detail/ckms_quantiles.h @@ -5,12 +5,14 @@ #include #include +#include "prometheus/detail/core_export.h" + namespace prometheus { namespace detail { -class CKMSQuantiles { +class PROMETHEUS_CPP_CORE_EXPORT CKMSQuantiles { public: - struct Quantile { + struct PROMETHEUS_CPP_CORE_EXPORT Quantile { const double quantile; const double error; const double u; diff --git a/core/include/prometheus/detail/time_window_quantiles.h b/core/include/prometheus/detail/time_window_quantiles.h index aeb42eeb..d2a90c31 100644 --- a/core/include/prometheus/detail/time_window_quantiles.h +++ b/core/include/prometheus/detail/time_window_quantiles.h @@ -5,11 +5,12 @@ #include #include "prometheus/detail/ckms_quantiles.h" +#include "prometheus/detail/core_export.h" namespace prometheus { namespace detail { -class TimeWindowQuantiles { +class PROMETHEUS_CPP_CORE_EXPORT TimeWindowQuantiles { using Clock = std::chrono::steady_clock; public: diff --git a/core/include/prometheus/detail/utils.h b/core/include/prometheus/detail/utils.h index 503c1b20..26d080a3 100644 --- a/core/include/prometheus/detail/utils.h +++ b/core/include/prometheus/detail/utils.h @@ -4,6 +4,8 @@ #include #include +#include "prometheus/detail/core_export.h" + namespace prometheus { namespace detail { @@ -13,7 +15,8 @@ namespace detail { /// \param labels The map that will be computed the hash value. /// /// \returns The hash value of the given labels. -std::size_t hash_labels(const std::map& labels); +PROMETHEUS_CPP_CORE_EXPORT std::size_t hash_labels( + const std::map& labels); } // namespace detail diff --git a/core/include/prometheus/family.h b/core/include/prometheus/family.h index 39904fc4..44b3c98b 100644 --- a/core/include/prometheus/family.h +++ b/core/include/prometheus/family.h @@ -15,6 +15,7 @@ #include "prometheus/check_names.h" #include "prometheus/client_metric.h" #include "prometheus/collectable.h" +#include "prometheus/detail/core_export.h" #include "prometheus/detail/future_std.h" #include "prometheus/detail/utils.h" #include "prometheus/metric_family.h" @@ -58,7 +59,7 @@ namespace prometheus { /// /// \tparam T One of the metric types Counter, Gauge, Histogram or Summary. template -class Family : public Collectable { +class PROMETHEUS_CPP_CORE_EXPORT Family : public Collectable { public: /// \brief Create a new metric. /// diff --git a/core/include/prometheus/gauge.h b/core/include/prometheus/gauge.h index 7d2f2f38..467115b2 100644 --- a/core/include/prometheus/gauge.h +++ b/core/include/prometheus/gauge.h @@ -4,6 +4,7 @@ #include "prometheus/client_metric.h" #include "prometheus/detail/builder.h" +#include "prometheus/detail/core_export.h" #include "prometheus/metric_type.h" namespace prometheus { @@ -20,7 +21,7 @@ namespace prometheus { /// /// The class is thread-safe. No concurrent call to any API of this type causes /// a data race. -class Gauge { +class PROMETHEUS_CPP_CORE_EXPORT Gauge { public: static const MetricType metric_type{MetricType::Gauge}; @@ -88,6 +89,6 @@ class Gauge { /// /// To finish the configuration of the Gauge metric register it with /// Register(Registry&). -detail::Builder BuildGauge(); +PROMETHEUS_CPP_CORE_EXPORT detail::Builder BuildGauge(); } // namespace prometheus diff --git a/core/include/prometheus/histogram.h b/core/include/prometheus/histogram.h index 582c4694..a9527870 100644 --- a/core/include/prometheus/histogram.h +++ b/core/include/prometheus/histogram.h @@ -5,6 +5,7 @@ #include "prometheus/client_metric.h" #include "prometheus/counter.h" #include "prometheus/detail/builder.h" +#include "prometheus/detail/core_export.h" #include "prometheus/metric_type.h" namespace prometheus { @@ -25,7 +26,7 @@ namespace prometheus { /// /// The class is thread-safe. No concurrent call to any API of this type causes /// a data race. -class Histogram { +class PROMETHEUS_CPP_CORE_EXPORT Histogram { public: using BucketBoundaries = std::vector; @@ -97,6 +98,6 @@ class Histogram { /// /// To finish the configuration of the Histogram metric register it with /// Register(Registry&). -detail::Builder BuildHistogram(); +PROMETHEUS_CPP_CORE_EXPORT detail::Builder BuildHistogram(); } // namespace prometheus diff --git a/core/include/prometheus/metric_family.h b/core/include/prometheus/metric_family.h index da913a45..1ba3f5a3 100644 --- a/core/include/prometheus/metric_family.h +++ b/core/include/prometheus/metric_family.h @@ -4,11 +4,12 @@ #include #include "prometheus/client_metric.h" +#include "prometheus/detail/core_export.h" #include "prometheus/metric_type.h" namespace prometheus { -struct MetricFamily { +struct PROMETHEUS_CPP_CORE_EXPORT MetricFamily { std::string name; std::string help; MetricType type = MetricType::Untyped; diff --git a/core/include/prometheus/registry.h b/core/include/prometheus/registry.h index ef15305a..69a0e4b4 100644 --- a/core/include/prometheus/registry.h +++ b/core/include/prometheus/registry.h @@ -7,6 +7,7 @@ #include #include "prometheus/collectable.h" +#include "prometheus/detail/core_export.h" #include "prometheus/detail/future_std.h" #include "prometheus/family.h" #include "prometheus/metric_family.h" @@ -32,7 +33,7 @@ class Builder; /// /// The class is thread-safe. No concurrent call to any API of this type causes /// a data race. -class Registry : public Collectable { +class PROMETHEUS_CPP_CORE_EXPORT Registry : public Collectable { public: /// \brief Returns a list of metrics and their samples. /// diff --git a/core/include/prometheus/serializer.h b/core/include/prometheus/serializer.h index 83bbd6e4..c55ae096 100644 --- a/core/include/prometheus/serializer.h +++ b/core/include/prometheus/serializer.h @@ -4,11 +4,12 @@ #include #include +#include "prometheus/detail/core_export.h" #include "prometheus/metric_family.h" namespace prometheus { -class Serializer { +class PROMETHEUS_CPP_CORE_EXPORT Serializer { public: virtual ~Serializer() = default; virtual std::string Serialize(const std::vector&) const; diff --git a/core/include/prometheus/summary.h b/core/include/prometheus/summary.h index b9eb9550..fd5914fb 100644 --- a/core/include/prometheus/summary.h +++ b/core/include/prometheus/summary.h @@ -8,6 +8,7 @@ #include "prometheus/client_metric.h" #include "prometheus/detail/ckms_quantiles.h" #include "prometheus/detail/builder.h" +#include "prometheus/detail/core_export.h" #include "prometheus/detail/time_window_quantiles.h" #include "prometheus/metric_type.h" @@ -37,7 +38,7 @@ namespace prometheus { /// /// The class is thread-safe. No concurrent call to any API of this type causes /// a data race. -class Summary { +class PROMETHEUS_CPP_CORE_EXPORT Summary { public: using Quantiles = std::vector; @@ -117,6 +118,6 @@ class Summary { /// /// To finish the configuration of the Summary metric register it with /// Register(Registry&). -detail::Builder BuildSummary(); +PROMETHEUS_CPP_CORE_EXPORT detail::Builder BuildSummary(); } // namespace prometheus diff --git a/core/include/prometheus/text_serializer.h b/core/include/prometheus/text_serializer.h index a12f0ec1..b1e22c00 100644 --- a/core/include/prometheus/text_serializer.h +++ b/core/include/prometheus/text_serializer.h @@ -4,12 +4,13 @@ #include #include +#include "prometheus/detail/core_export.h" #include "prometheus/metric_family.h" #include "prometheus/serializer.h" namespace prometheus { -class TextSerializer : public Serializer { +class PROMETHEUS_CPP_CORE_EXPORT TextSerializer : public Serializer { public: using Serializer::Serialize; void Serialize(std::ostream& out, diff --git a/core/src/counter.cc b/core/src/counter.cc index 1b2c738c..2aa5ba4b 100644 --- a/core/src/counter.cc +++ b/core/src/counter.cc @@ -18,8 +18,8 @@ ClientMetric Counter::Collect() const { return metric; } -template class detail::Builder; -template class Family; +template class PROMETHEUS_CPP_CORE_EXPORT detail::Builder; +template class PROMETHEUS_CPP_CORE_EXPORT Family; template Family& Registry::Add( const std::string& name, const std::string& help, diff --git a/core/src/gauge.cc b/core/src/gauge.cc index 7a000e7d..cba54025 100644 --- a/core/src/gauge.cc +++ b/core/src/gauge.cc @@ -49,8 +49,8 @@ ClientMetric Gauge::Collect() const { return metric; } -template class Family; -template class detail::Builder; +template class PROMETHEUS_CPP_CORE_EXPORT Family; +template class PROMETHEUS_CPP_CORE_EXPORT detail::Builder; template Family& Registry::Add( const std::string& name, const std::string& help, diff --git a/core/src/histogram.cc b/core/src/histogram.cc index c059b136..4f8446e9 100644 --- a/core/src/histogram.cc +++ b/core/src/histogram.cc @@ -61,8 +61,8 @@ ClientMetric Histogram::Collect() const { return metric; } -template class Family; -template class detail::Builder; +template class PROMETHEUS_CPP_CORE_EXPORT Family; +template class PROMETHEUS_CPP_CORE_EXPORT detail::Builder; template Family& Registry::Add( const std::string& name, const std::string& help, diff --git a/core/src/summary.cc b/core/src/summary.cc index cfc3fa0d..1504b264 100644 --- a/core/src/summary.cc +++ b/core/src/summary.cc @@ -38,8 +38,8 @@ ClientMetric Summary::Collect() { return metric; } -template class Family; -template class detail::Builder; +template class PROMETHEUS_CPP_CORE_EXPORT Family; +template class PROMETHEUS_CPP_CORE_EXPORT detail::Builder; template Family& Registry::Add( const std::string& name, const std::string& help, diff --git a/pull/CMakeLists.txt b/pull/CMakeLists.txt index edca4033..4d0fa2b8 100644 --- a/pull/CMakeLists.txt +++ b/pull/CMakeLists.txt @@ -18,6 +18,11 @@ add_library(pull add_library(${PROJECT_NAME}::pull ALIAS pull) +generate_export_header(pull + EXPORT_FILE_NAME include/prometheus/detail/pull_export.h + PREFIX_NAME PROMETHEUS_CPP_ +) + target_link_libraries(pull PUBLIC ${PROJECT_NAME}::core @@ -31,6 +36,7 @@ target_link_libraries(pull target_include_directories(pull PUBLIC $ + $ PRIVATE ${CIVETWEB_INCLUDE_DIRS} ) @@ -40,7 +46,12 @@ target_compile_definitions(pull $<$:HAVE_ZLIB> ) -set_target_properties(pull PROPERTIES OUTPUT_NAME ${PROJECT_NAME}-pull) +set_target_properties(pull + PROPERTIES + OUTPUT_NAME ${PROJECT_NAME}-pull + VERSION "${PROJECT_VERSION}" + SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}" +) install( TARGETS pull @@ -52,7 +63,7 @@ install( ) install( - DIRECTORY include/ + DIRECTORY include/ ${CMAKE_CURRENT_BINARY_DIR}/include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) diff --git a/pull/include/prometheus/exposer.h b/pull/include/prometheus/exposer.h index 611004ba..c730360c 100644 --- a/pull/include/prometheus/exposer.h +++ b/pull/include/prometheus/exposer.h @@ -7,6 +7,7 @@ #include #include "prometheus/collectable.h" +#include "prometheus/detail/pull_export.h" #include "prometheus/registry.h" class CivetServer; @@ -17,7 +18,7 @@ namespace detail { class MetricsHandler; } // namespace detail -class Exposer { +class PROMETHEUS_CPP_PULL_EXPORT Exposer { public: explicit Exposer(const std::string& bind_address, const std::string& uri = std::string("/metrics"), diff --git a/push/CMakeLists.txt b/push/CMakeLists.txt index 4e4002e2..48ddeca3 100644 --- a/push/CMakeLists.txt +++ b/push/CMakeLists.txt @@ -7,6 +7,11 @@ add_library(push add_library(${PROJECT_NAME}::push ALIAS push) +generate_export_header(push + EXPORT_FILE_NAME include/prometheus/detail/push_export.h + PREFIX_NAME PROMETHEUS_CPP_ +) + target_link_libraries(push PUBLIC ${PROJECT_NAME}::core @@ -19,11 +24,17 @@ target_link_libraries(push target_include_directories(push PUBLIC $ + $ PRIVATE ${CURL_INCLUDE_DIRS} ) -set_target_properties(push PROPERTIES OUTPUT_NAME ${PROJECT_NAME}-push) +set_target_properties(push + PROPERTIES + OUTPUT_NAME ${PROJECT_NAME}-push + VERSION "${PROJECT_VERSION}" + SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}" +) install( TARGETS push @@ -35,7 +46,7 @@ install( ) install( - DIRECTORY include/ + DIRECTORY include/ ${CMAKE_CURRENT_BINARY_DIR}/include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) diff --git a/push/include/prometheus/gateway.h b/push/include/prometheus/gateway.h index 1456d99c..5d48cba8 100644 --- a/push/include/prometheus/gateway.h +++ b/push/include/prometheus/gateway.h @@ -7,11 +7,12 @@ #include #include +#include "prometheus/detail/push_export.h" #include "prometheus/registry.h" namespace prometheus { -class Gateway { +class PROMETHEUS_CPP_PUSH_EXPORT Gateway { public: using Labels = std::map; From b6a1b4c2fc21931012ed035ecec36bd967345123 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 31 Aug 2019 19:35:03 +0200 Subject: [PATCH 034/206] Implement symbol visibility build system agnostic Issue: #223 --- CMakeLists.txt | 2 +- core/BUILD.bazel | 3 +++ core/CMakeLists.txt | 9 ++------- core/include/prometheus/detail/core_export.h | 11 +++++++++++ pull/BUILD.bazel | 1 + pull/CMakeLists.txt | 9 ++------- pull/include/prometheus/detail/pull_export.h | 11 +++++++++++ push/BUILD.bazel | 3 +++ push/CMakeLists.txt | 9 ++------- push/include/prometheus/detail/push_export.h | 11 +++++++++++ 10 files changed, 47 insertions(+), 22 deletions(-) create mode 100644 core/include/prometheus/detail/core_export.h create mode 100644 pull/include/prometheus/detail/pull_export.h create mode 100644 push/include/prometheus/detail/push_export.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 980ee7e0..2ad9f44a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,12 +3,12 @@ cmake_minimum_required(VERSION 3.5 FATAL_ERROR) project(prometheus-cpp VERSION 0.8.0) -include(GenerateExportHeader) include(GNUInstallDirs) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +option(BUILD_SHARED_LIBS "Build libraries as shared ones" OFF) option(ENABLE_PULL "Build prometheus-cpp pull library" ON) option(ENABLE_PUSH "Build prometheus-cpp push library" ON) option(ENABLE_COMPRESSION "Enable gzip compression" ON) diff --git a/core/BUILD.bazel b/core/BUILD.bazel index 263c37b8..4105ff77 100644 --- a/core/BUILD.bazel +++ b/core/BUILD.bazel @@ -7,6 +7,9 @@ cc_library( hdrs = glob( ["include/**/*.h"], ), + copts = [ + "-DPROMETHEUS_CPP_COMPILE_CORE", + ], strip_include_prefix = "include", visibility = ["//visibility:public"], ) diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 619672ea..e2d18912 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -18,11 +18,6 @@ add_library(core add_library(${PROJECT_NAME}::core ALIAS core) -generate_export_header(core - EXPORT_FILE_NAME include/prometheus/detail/core_export.h - PREFIX_NAME PROMETHEUS_CPP_ -) - target_link_libraries(core PRIVATE Threads::Threads @@ -32,12 +27,12 @@ target_link_libraries(core target_include_directories(core PUBLIC $ - $ ) set_target_properties(core PROPERTIES OUTPUT_NAME ${PROJECT_NAME}-core + DEFINE_SYMBOL PROMETHEUS_CPP_COMPILE_CORE VERSION "${PROJECT_VERSION}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}" ) @@ -52,7 +47,7 @@ install( ) install( - DIRECTORY include/ ${CMAKE_CURRENT_BINARY_DIR}/include/ + DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) diff --git a/core/include/prometheus/detail/core_export.h b/core/include/prometheus/detail/core_export.h new file mode 100644 index 00000000..e4f9e383 --- /dev/null +++ b/core/include/prometheus/detail/core_export.h @@ -0,0 +1,11 @@ +#pragma once + +#if defined(_WIN32) +# ifdef PROMETHEUS_CPP_COMPILE_CORE +# define PROMETHEUS_CPP_CORE_EXPORT __declspec(dllexport) +# else +# define PROMETHEUS_CPP_CORE_EXPORT __declspec(dllimport) +# endif +#else +# define PROMETHEUS_CPP_CORE_EXPORT __attribute__((visibility("default"))) +#endif diff --git a/pull/BUILD.bazel b/pull/BUILD.bazel index a5ae5df7..f85a3d1b 100644 --- a/pull/BUILD.bazel +++ b/pull/BUILD.bazel @@ -9,6 +9,7 @@ cc_library( ), copts = [ "-DHAVE_ZLIB", + "-DPROMETHEUS_CPP_COMPILE_PULL", ], strip_include_prefix = "include", visibility = ["//visibility:public"], diff --git a/pull/CMakeLists.txt b/pull/CMakeLists.txt index 4d0fa2b8..29ae695e 100644 --- a/pull/CMakeLists.txt +++ b/pull/CMakeLists.txt @@ -18,11 +18,6 @@ add_library(pull add_library(${PROJECT_NAME}::pull ALIAS pull) -generate_export_header(pull - EXPORT_FILE_NAME include/prometheus/detail/pull_export.h - PREFIX_NAME PROMETHEUS_CPP_ -) - target_link_libraries(pull PUBLIC ${PROJECT_NAME}::core @@ -36,7 +31,6 @@ target_link_libraries(pull target_include_directories(pull PUBLIC $ - $ PRIVATE ${CIVETWEB_INCLUDE_DIRS} ) @@ -49,6 +43,7 @@ target_compile_definitions(pull set_target_properties(pull PROPERTIES OUTPUT_NAME ${PROJECT_NAME}-pull + DEFINE_SYMBOL PROMETHEUS_CPP_COMPILE_PULL VERSION "${PROJECT_VERSION}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}" ) @@ -63,7 +58,7 @@ install( ) install( - DIRECTORY include/ ${CMAKE_CURRENT_BINARY_DIR}/include/ + DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) diff --git a/pull/include/prometheus/detail/pull_export.h b/pull/include/prometheus/detail/pull_export.h new file mode 100644 index 00000000..92624749 --- /dev/null +++ b/pull/include/prometheus/detail/pull_export.h @@ -0,0 +1,11 @@ +#pragma once + +#if defined(_WIN32) +# ifdef PROMETHEUS_CPP_COMPILE_PULL +# define PROMETHEUS_CPP_PULL_EXPORT __declspec(dllexport) +# else +# define PROMETHEUS_CPP_PULL_EXPORT __declspec(dllimport) +# endif +#else +# define PROMETHEUS_CPP_PULL_EXPORT __attribute__((visibility("default"))) +#endif diff --git a/push/BUILD.bazel b/push/BUILD.bazel index 15d44c09..70c13f23 100644 --- a/push/BUILD.bazel +++ b/push/BUILD.bazel @@ -7,6 +7,9 @@ cc_library( hdrs = glob( ["include/**/*.h"], ), + copts = [ + "-DPROMETHEUS_CPP_COMPILE_PUSH", + ], linkopts = select({ "//:windows": [], "//:windows_msvc": [], diff --git a/push/CMakeLists.txt b/push/CMakeLists.txt index 48ddeca3..b62b473e 100644 --- a/push/CMakeLists.txt +++ b/push/CMakeLists.txt @@ -7,11 +7,6 @@ add_library(push add_library(${PROJECT_NAME}::push ALIAS push) -generate_export_header(push - EXPORT_FILE_NAME include/prometheus/detail/push_export.h - PREFIX_NAME PROMETHEUS_CPP_ -) - target_link_libraries(push PUBLIC ${PROJECT_NAME}::core @@ -24,7 +19,6 @@ target_link_libraries(push target_include_directories(push PUBLIC $ - $ PRIVATE ${CURL_INCLUDE_DIRS} ) @@ -32,6 +26,7 @@ target_include_directories(push set_target_properties(push PROPERTIES OUTPUT_NAME ${PROJECT_NAME}-push + DEFINE_SYMBOL PROMETHEUS_CPP_COMPILE_PUSH VERSION "${PROJECT_VERSION}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}" ) @@ -46,7 +41,7 @@ install( ) install( - DIRECTORY include/ ${CMAKE_CURRENT_BINARY_DIR}/include/ + DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) diff --git a/push/include/prometheus/detail/push_export.h b/push/include/prometheus/detail/push_export.h new file mode 100644 index 00000000..fe714a2b --- /dev/null +++ b/push/include/prometheus/detail/push_export.h @@ -0,0 +1,11 @@ +#pragma once + +#if defined(_WIN32) +# ifdef PROMETHEUS_CPP_COMPILE_PUSH +# define PROMETHEUS_CPP_PUSH_EXPORT __declspec(dllexport) +# else +# define PROMETHEUS_CPP_PUSH_EXPORT __declspec(dllimport) +# endif +#else +# define PROMETHEUS_CPP_PUSH_EXPORT __attribute__((visibility("default"))) +#endif From 20475b39199afaba170334bcec4ff4d7b31f190d Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 31 Aug 2019 20:50:59 +0200 Subject: [PATCH 035/206] cmake: Put DLLs and binaries into same directory --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ad9f44a..0713a8fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,11 @@ if(OVERRIDE_CXX_STANDARD_FLAGS) set(CMAKE_CXX_EXTENSIONS Off) endif() +# Put DLLs and binaries into same directory +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) + # Hide things by default for shared libraries if(BUILD_SHARED_LIBS) set(CMAKE_C_VISIBILITY_PRESET hidden) From 5f443f16a5ce74aba69d0c0a0ab943d6c37ffddc Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 22 Sep 2019 18:34:24 +0200 Subject: [PATCH 036/206] Use github actions Closes: #295 --- .github/scripts/run-bazel-test | 19 ++++++++ .github/scripts/run-bazel-test.cmd | 5 ++ .github/scripts/run-cmake-test | 44 +++++++++++++++++ .github/scripts/run-cmake-test.cmd | 7 +++ .github/scripts/run-prepare | 47 +++++++++++++++++++ .github/scripts/run-prepare.cmd | 3 ++ .../continuous-integration-workflow.yml | 22 +++++++++ 7 files changed, 147 insertions(+) create mode 100755 .github/scripts/run-bazel-test create mode 100644 .github/scripts/run-bazel-test.cmd create mode 100755 .github/scripts/run-cmake-test create mode 100644 .github/scripts/run-cmake-test.cmd create mode 100755 .github/scripts/run-prepare create mode 100644 .github/scripts/run-prepare.cmd create mode 100644 .github/workflows/continuous-integration-workflow.yml diff --git a/.github/scripts/run-bazel-test b/.github/scripts/run-bazel-test new file mode 100755 index 00000000..48261b95 --- /dev/null +++ b/.github/scripts/run-bazel-test @@ -0,0 +1,19 @@ +#!/bin/bash + +set -euo pipefail + +WORKSPACE=$(cd "$(dirname "${BASH_SOURCE[0]}")"/../.. && /bin/pwd -P) + +OS_ARG=${1:?} + +bazel build //... + +bazel test --test_output=all //core/... //pull/... +bazel test --test_output=all //pull/tests/integration:scrape-test + +#if [[ "${OS_ARG}" == "macOS"* ]] +#then +# bazel test --test_output=all //pull/tests/integration:lint-test +#fi + +bazel run -c opt //core/benchmarks diff --git a/.github/scripts/run-bazel-test.cmd b/.github/scripts/run-bazel-test.cmd new file mode 100644 index 00000000..1055c1c7 --- /dev/null +++ b/.github/scripts/run-bazel-test.cmd @@ -0,0 +1,5 @@ +bazel build //... || EXIT /B 1 + +bazel test --test_output=all //core/... //pull/... || EXIT /B 1 + +bazel run -c opt //core/benchmarks || EXIT /B 1 diff --git a/.github/scripts/run-cmake-test b/.github/scripts/run-cmake-test new file mode 100755 index 00000000..b3dfe688 --- /dev/null +++ b/.github/scripts/run-cmake-test @@ -0,0 +1,44 @@ +#!/bin/bash + +set -euo pipefail + +WORKSPACE=$(cd "$(dirname "${BASH_SOURCE[0]}")"/../.. && /bin/pwd -P) +THIRDPARTY_PREFIX_DIR="${WORKSPACE}/_opt" + +# Build with internal dependencies + +mkdir "${WORKSPACE}/_build_internal_deps" && cd $_ +cmake .. -DUSE_THIRDPARTY_LIBRARIES=ON -DENABLE_WARNINGS_AS_ERRORS=ON +make -j$(nproc) +ctest -V +mkdir -p deploy +make DESTDIR="${PWD}/deploy" install + +# Build dependencies + +mkdir "${WORKSPACE}/_build_civetweb" && cd $_ +cmake "${WORKSPACE}/3rdparty/civetweb" -DCMAKE_INSTALL_PREFIX="${THIRDPARTY_PREFIX_DIR}" -DCIVETWEB_ENABLE_CXX=ON -DCIVETWEB_ENABLE_SSL=OFF -DCIVETWEB_BUILD_TESTING=OFF +make -j$(nproc) +make install + +mkdir "${WORKSPACE}/_build_googletest" && cd $_ +cmake "${WORKSPACE}/3rdparty/googletest" -DCMAKE_INSTALL_PREFIX="${THIRDPARTY_PREFIX_DIR}" +make -j$(nproc) +make install + +# Build with external dependencies and test coverage + +mkdir "${WORKSPACE}/_build_coverage" && cd $_ +CFLAGS="--coverage" CXXFLAGS="--coverage" LDFLAGS="--coverage" cmake .. -DCMAKE_INSTALL_PREFIX="${THIRDPARTY_PREFIX_DIR}" -DUSE_THIRDPARTY_LIBRARIES=OFF +make -j$(nproc) +ctest -V -LE Benchmark +mkdir -p deploy +make DESTDIR="${PWD}/deploy" install + +# Collect coverage data + +#if [[ "${OS_ARG}" == "ubuntu"* ]] +#then +# pip install --user cpp-coveralls +# coveralls --root .. --build-root . -E ".*/3rdparty/.*" -E ".*/_.*" -E ".*/tests/.*" -E ".*/benchmarks/.*" +#fi diff --git a/.github/scripts/run-cmake-test.cmd b/.github/scripts/run-cmake-test.cmd new file mode 100644 index 00000000..eebb4525 --- /dev/null +++ b/.github/scripts/run-cmake-test.cmd @@ -0,0 +1,7 @@ +mkdir "_build_internal_deps" || EXIT /B 1 +cd "_build_internal_deps" || EXIT /B 1 +cmake .. -DUSE_THIRDPARTY_LIBRARIES=ON -DENABLE_WARNINGS_AS_ERRORS=ON -DENABLE_COMPRESSION=OFF -DENABLE_PUSH=OFF || EXIT /B 1 +cmake --build . --config Debug || EXIT /B 1 +cmake --build . --config Release || EXIT /B 1 +ctest -C Debug -V -LE Benchmark || EXIT /B 1 +ctest -C Release -V || EXIT /B 1 diff --git a/.github/scripts/run-prepare b/.github/scripts/run-prepare new file mode 100755 index 00000000..32b4c443 --- /dev/null +++ b/.github/scripts/run-prepare @@ -0,0 +1,47 @@ +#!/bin/bash + +set -euo pipefail + +BUILDSYSTEM_ARG=${1:?} +OS_ARG=${2:?} + +case "${OS_ARG}" in + ubuntu*) + packages=(locales) + + case "${BUILDSYSTEM_ARG}" in + bazel) + curl -sL https://bazel.build/bazel-release.pub.gpg | sudo apt-key add - + echo "deb [arch=amd64] https://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list + packages+=(bazel) + ;; + cmake) + packages+=(libcurl4-openssl-dev) + ;; + esac + + curl -sL https://repos.influxdata.com/influxdb.key | sudo apt-key add - + source /etc/lsb-release + echo "deb https://repos.influxdata.com/${DISTRIB_ID,,} ${DISTRIB_CODENAME} stable" | sudo tee /etc/apt/sources.list.d/influxdb.list + packages+=(telegraf) + + sudo apt-get remove -y --purge man-db # avoid time-consuming trigger + sudo apt-get update + sudo apt-get install -y "${packages[@]}" + sudo locale-gen de_DE.UTF-8 # used by SerializerTest + ;; + + macOS*) + packages=(google-benchmark prometheus telegraf) + + case "${BUILDSYSTEM_ARG}" in + bazel) + packages+=(bazelbuild/tap/bazel) + ;; + cmake) + ;; + esac + + brew install "${packages[@]}" + ;; +esac diff --git a/.github/scripts/run-prepare.cmd b/.github/scripts/run-prepare.cmd new file mode 100644 index 00000000..c6789a10 --- /dev/null +++ b/.github/scripts/run-prepare.cmd @@ -0,0 +1,3 @@ +if [%1] == [bazel] ( + choco install bazel -y || EXIT /B 1 +) diff --git a/.github/workflows/continuous-integration-workflow.yml b/.github/workflows/continuous-integration-workflow.yml new file mode 100644 index 00000000..ddcf39cf --- /dev/null +++ b/.github/workflows/continuous-integration-workflow.yml @@ -0,0 +1,22 @@ +name: Continuous Integration +on: [push, pull_request] + +jobs: + build: + name: ${{ matrix.buildsystem }} on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + buildsystem: [bazel, cmake] + os: [macOS-10.14, ubuntu-16.04, windows-2016] + exclude: + - os: windows-2016 + buildsystem: bazel + steps: + - uses: actions/checkout@master + with: + submodules: true + - name: Prepare + run: .github/scripts/run-prepare ${{ matrix.buildsystem }} ${{ matrix.os }} + - name: Test + run: .github/scripts/run-${{ matrix.buildsystem }}-test ${{ matrix.os }} From 3667f3ebb12fa679872f5f7e6c6d2e19df9a285f Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 26 Sep 2019 22:16:52 +0200 Subject: [PATCH 037/206] core: Do not run locale test on Windows --- core/tests/serializer_test.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/tests/serializer_test.cc b/core/tests/serializer_test.cc index 4e915306..f935a3b0 100644 --- a/core/tests/serializer_test.cc +++ b/core/tests/serializer_test.cc @@ -23,6 +23,7 @@ class SerializerTest : public testing::Test { TextSerializer textSerializer; }; +#ifndef _WIN32 TEST_F(SerializerTest, shouldSerializeLocaleIndependent) { // save and change locale const std::locale oldLocale = std::locale::classic(); @@ -34,6 +35,7 @@ TEST_F(SerializerTest, shouldSerializeLocaleIndependent) { // restore locale std::locale::global(oldLocale); } +#endif TEST_F(SerializerTest, shouldRestoreStreamState) { std::ostringstream os; From 26ce7bc049dd1f95ecfa9ed8aacbaa1a849e7abf Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 26 Sep 2019 22:21:25 +0200 Subject: [PATCH 038/206] Strip down Travis CI file --- .travis.yml | 50 +++++--------------------------------------------- 1 file changed, 5 insertions(+), 45 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9e523537..d2c814a6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,19 +7,10 @@ env: - secure: "DwlWRs05m1pw3/NprZdVRy3Vog7k+KYIW4O1YQczbKk0t64vYLJMxMh9D8HrngnUv1UDOOU2orEO/hYYjlmiNRqoMA0Me+q9ndqEGjdCvFketH7zYpPXMxV/Uk1E7yYK60CJYbCFK7NossBWlBwSIETUNXXz1MhqF4c7SwDCTQk6ybPUThJVI3/nZLC4Wn9DB4pxPkEZaXJLL3HU0vXH1r0vKRFsjBU0OtDx1KQgtFYVmWbmd7tpxAlDfI11HJjpaoFD6HHcTlwvM5Ogj4lWL8Ze3glJsSsAYntEqgm7GQa4tYWsYmvGC5554WwIQ/0cDsSTLZjk2+FtSGmJpxdwXwmfOzzVjt7Ise7KG2Zg+CZ/IwF9VpwP2xmH/ug926sJDIjMmehZx2eetDzwY3oB3g3AF+JJIoaDF14Skt6QXEFWm/s/PiSQwkenMF80xzUufB7CRCVLR054HfJsQ0m5O8bNtUjyH7byZwOjvz8t/VdlnfFn5Ccs4tniOK6iiwvKmGAaakv6pfA7xKpRbExFkgPoTmejeQX83Ee1/A4JySMPTxkHPsJbMhimpMdbLVJTh9mKJxo2kleCC0MKB7OwTyNwUdR8+nqoZpUknGX6BrGY+R6ou3xlNYRUM9LCxxBKBJB05CswbhRWroun9fbpDTzBz3XPwBjiVTlxUc/YnXA=" - secure: "fg0cACBBm7NAjad4Pxhp9DeTGDbcLnD0U9uxclsioTcB5X+88sTsgKRr5gG0hajPG6QF0L8iNt7zp87eZNcSU7JlTWnCBHPAAADD2apFnPUhioth+vPUBsUiKdOksoEG1q/hrjMYQ6yAf3XXd0+/ZaUA1X5v0OA2rjMTpNpNvMaQEN7M3XvcLRr1ydaAD/Wc1PAbuK8owWU3Hyo7+GdxoUWOtYiH44OuHSlSlnVQw2/yRR53yM1StKLZ2xarsWviXr76e1PutqoeeTbBbpAU6xboiyyDVey4Ae83HfOgPiADtsE4UjE2pqX2oqponY2q+0j8kI7sZVODR20nLCKcq9RHJR+yi0JEpsrqC4SE0lPKxG8HHlDaH+NdRVHTdNYuCfENR0R4YX/K59I83kLEnLNpC+j1BzXiRBjYzAMl5UtEDCUQGJcixq6BxE7i1uwskPckmYi2K63TaIxj5nvVm4Um8aHPrWHtbAf4stTDQHcFGcfQeBbX7PswKJAyIljaHn5T7kwAatRuWLHGsVTuxTkhkYohZy+/SDhFakI+6jfz8XZtL8gOIGMnDuvDWT2Di1JPZkBLcKKWpCIXdDaJnTogNid9xBpsX5IMVmlS51FxCOkoIT62gc9Lo+rxwgqFvEe+QIQh2zd8OjgS5m5HsftxCKVCbcPr+RjsNsCyOnQ=" - secure: "ijrdtLO7y18oJTcISP1Zl0+O8dbCmo8DB4+3N6kZ9JjL1rVF5NM9nCsaCQ6vmHFOsUjEehvGJR6ZYFOYOMBU11rCPqd2FrEPewtQ0qEYI8eOV062oa/DOxHKyzGPde8eHcopw6b44EjPXx4iZTabcU8U00azNyWinVxKtP8lHJiVH+waNejuoAuMKypM9Lz+RCz/TLg4+DpLvQ5kWfpcFsuBCBAMbCK6Ujmv5mscvKxmWLr2Z79Wl3i5MbBe3IuaDAKXTz0ponkvZCssPr/USD9AA04EEn/Eg95JXOtRUi6Ah/fUBDAF4Ez/7yOHsXD1y8xt332eE8nJqjX3eLqEdplT19M/hBsbXxNCL0iZSZ8LL0JHKYG5beDGvfZmrk4/Nj/qd3Es1NGT6q2kbkrbxWSEFdkniQuwfr+yvAoGv4XFdRMTPH321WrL8wxfud0b2OPMMJo6obDOgRZfHe6c+4Eo9i/G98eL7xOz0kUUILiex8IQKNWnYflH1CqRKBbNs0APAMMlFKQ8FVwLiu/OzA8mjI+CuPGxOdfilgsJfCvKMBvz12y2AIBHdVBf1T6Ph8NZpwKivNYt70QOu5J/rg5K6E6XY1faMgWuDzQkMaeof1esU1IVlXqKBWa9c9rMNHQHTvhZ2KZ1EZvNrCX1fnY/X8fuwnhJ1Aq1nzhJTrM=" -os: - - linux - - osx addons: apt: - sources: - - sourceline: 'deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8' - key_url: 'https://storage.googleapis.com/bazel-apt/doc/apt-key.pub.gpg' - - sourceline: 'deb https://repos.influxdata.com/ubuntu xenial stable' - key_url: 'https://repos.influxdata.com/influxdb.key' packages: - - bazel - cmake - curl - doxygen @@ -29,52 +20,22 @@ addons: - lcov - libcurl4-openssl-dev - python-pip - - telegraf - homebrew: - update: true - packages: - - cmake - - bazelbuild/tap/bazel - - google-benchmark - - prometheus - - telegraf - taps: - - bazelbuild/tap script: - - bazel build //... - - bazel test --test_output=all //core/... //pull/... - - bazel test --test_output=all //pull/tests/integration:scrape-test -# - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then bazel test --test_output=all //pull/tests/integration:lint-test; fi - - bazel run -c opt //core/benchmarks - - - pushd . - - mkdir _build_internal_deps - - cd _build_internal_deps - - cmake .. -DUSE_THIRDPARTY_LIBRARIES=ON -DENABLE_WARNINGS_AS_ERRORS=ON - - make -j 4 - - ctest -V - - mkdir -p deploy - - make DESTDIR=`pwd`/deploy install - - popd - - - 3rdparty/build_for_travis.sh - - rm -rf 3rdparty/* - - pushd . - mkdir _build_coverage - cd _build_coverage - - CFLAGS="--coverage" CXXFLAGS="--coverage" LDFLAGS="--coverage" cmake .. -DCMAKE_INSTALL_PREFIX=../_opt -DUSE_THIRDPARTY_LIBRARIES=OFF + - CFLAGS="--coverage" CXXFLAGS="--coverage" LDFLAGS="--coverage" cmake .. -DUSE_THIRDPARTY_LIBRARIES=ON - make -j 4 - ctest -V -LE Benchmark - - mkdir -p deploy - - make DESTDIR=`pwd`/deploy install - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then pip install --user cpp-coveralls && coveralls --root .. --build-root . -E ".*/3rdparty/.*" -E ".*/_.*" -E ".*/tests/.*" -E ".*/benchmarks/.*"; fi + - pip install --user cpp-coveralls + - coveralls --root .. --build-root . -E ".*/3rdparty/.*" -E ".*/_.*" -E ".*/tests/.*" -E ".*/benchmarks/.*" - popd - pushd . - cd doc - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then doxygen && touch html/.nojekyll; fi + - doxygen + - touch html/.nojekyll - popd deploy: @@ -84,4 +45,3 @@ deploy: skip-cleanup: true on: branch: master - condition: $TRAVIS_OS_NAME == linux From 815bfb9b296cab3e23b5ca2cf25b8eeadbb4bbec Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 17 Oct 2019 17:58:31 +0200 Subject: [PATCH 039/206] chore(bazel): Use local_defines instead of copts --- core/BUILD.bazel | 4 ++-- pull/BUILD.bazel | 6 +++--- push/BUILD.bazel | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/core/BUILD.bazel b/core/BUILD.bazel index 4105ff77..b1eb862f 100644 --- a/core/BUILD.bazel +++ b/core/BUILD.bazel @@ -7,8 +7,8 @@ cc_library( hdrs = glob( ["include/**/*.h"], ), - copts = [ - "-DPROMETHEUS_CPP_COMPILE_CORE", + local_defines = [ + "PROMETHEUS_CPP_COMPILE_CORE", ], strip_include_prefix = "include", visibility = ["//visibility:public"], diff --git a/pull/BUILD.bazel b/pull/BUILD.bazel index f85a3d1b..c0c1e582 100644 --- a/pull/BUILD.bazel +++ b/pull/BUILD.bazel @@ -7,9 +7,9 @@ cc_library( hdrs = glob( ["include/**/*.h"], ), - copts = [ - "-DHAVE_ZLIB", - "-DPROMETHEUS_CPP_COMPILE_PULL", + local_defines = [ + "HAVE_ZLIB", + "PROMETHEUS_CPP_COMPILE_PULL", ], strip_include_prefix = "include", visibility = ["//visibility:public"], diff --git a/push/BUILD.bazel b/push/BUILD.bazel index 70c13f23..7bcb446d 100644 --- a/push/BUILD.bazel +++ b/push/BUILD.bazel @@ -7,14 +7,14 @@ cc_library( hdrs = glob( ["include/**/*.h"], ), - copts = [ - "-DPROMETHEUS_CPP_COMPILE_PUSH", - ], linkopts = select({ "//:windows": [], "//:windows_msvc": [], "//conditions:default": ["-lpthread"], }), + local_defines = [ + "PROMETHEUS_CPP_COMPILE_PUSH", + ], strip_include_prefix = "include", visibility = ["//visibility:public"], deps = [ From 203f7f6e70728dbd68e29f06d2e848c45bc02156 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 17 Oct 2019 18:07:44 +0200 Subject: [PATCH 040/206] chore(bazel): Use True / False in boolean context --- core/benchmarks/BUILD.bazel | 2 +- core/tests/BUILD.bazel | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/benchmarks/BUILD.bazel b/core/benchmarks/BUILD.bazel index bd48104e..3efb7be3 100644 --- a/core/benchmarks/BUILD.bazel +++ b/core/benchmarks/BUILD.bazel @@ -4,7 +4,7 @@ cc_binary( "*.cc", "*.h", ]), - linkstatic = 1, + linkstatic = True, deps = [ "//core", "@com_github_google_benchmark//:benchmark", diff --git a/core/tests/BUILD.bazel b/core/tests/BUILD.bazel index f82aa5ae..c00fb2bf 100644 --- a/core/tests/BUILD.bazel +++ b/core/tests/BUILD.bazel @@ -5,7 +5,7 @@ cc_test( "*.h", ]), copts = ["-Iexternal/googletest/include"], - linkstatic = 1, + linkstatic = True, deps = [ "//core", "@com_google_googletest//:gtest_main", From c216ae7ae9a782f94c14b448f97c03f1de374f5c Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 17 Oct 2019 18:13:24 +0200 Subject: [PATCH 041/206] chore(clang-format): Format everything --- core/benchmarks/summary_bench.cc | 2 +- core/include/prometheus/detail/core_export.h | 12 ++++++------ core/include/prometheus/summary.h | 2 +- core/src/histogram.cc | 9 ++++++--- core/tests/histogram_test.cc | 3 +-- core/tests/registry_test.cc | 2 +- pull/include/prometheus/detail/pull_export.h | 12 ++++++------ pull/src/exposer.cc | 10 +++++----- push/include/prometheus/detail/push_export.h | 12 ++++++------ 9 files changed, 33 insertions(+), 31 deletions(-) diff --git a/core/benchmarks/summary_bench.cc b/core/benchmarks/summary_bench.cc index 95596002..2a55ef95 100644 --- a/core/benchmarks/summary_bench.cc +++ b/core/benchmarks/summary_bench.cc @@ -2,8 +2,8 @@ #include #include -#include #include +#include using prometheus::Summary; diff --git a/core/include/prometheus/detail/core_export.h b/core/include/prometheus/detail/core_export.h index e4f9e383..8517f9b2 100644 --- a/core/include/prometheus/detail/core_export.h +++ b/core/include/prometheus/detail/core_export.h @@ -1,11 +1,11 @@ #pragma once #if defined(_WIN32) -# ifdef PROMETHEUS_CPP_COMPILE_CORE -# define PROMETHEUS_CPP_CORE_EXPORT __declspec(dllexport) -# else -# define PROMETHEUS_CPP_CORE_EXPORT __declspec(dllimport) -# endif +#ifdef PROMETHEUS_CPP_COMPILE_CORE +#define PROMETHEUS_CPP_CORE_EXPORT __declspec(dllexport) #else -# define PROMETHEUS_CPP_CORE_EXPORT __attribute__((visibility("default"))) +#define PROMETHEUS_CPP_CORE_EXPORT __declspec(dllimport) +#endif +#else +#define PROMETHEUS_CPP_CORE_EXPORT __attribute__((visibility("default"))) #endif diff --git a/core/include/prometheus/summary.h b/core/include/prometheus/summary.h index fd5914fb..5cec9673 100644 --- a/core/include/prometheus/summary.h +++ b/core/include/prometheus/summary.h @@ -6,8 +6,8 @@ #include #include "prometheus/client_metric.h" -#include "prometheus/detail/ckms_quantiles.h" #include "prometheus/detail/builder.h" +#include "prometheus/detail/ckms_quantiles.h" #include "prometheus/detail/core_export.h" #include "prometheus/detail/time_window_quantiles.h" #include "prometheus/metric_type.h" diff --git a/core/src/histogram.cc b/core/src/histogram.cc index 4f8446e9..703acaf5 100644 --- a/core/src/histogram.cc +++ b/core/src/histogram.cc @@ -31,14 +31,17 @@ void Histogram::Observe(const double value) { void Histogram::ObserveMultiple(const std::vector bucket_increments, const double sum_of_values) { if (bucket_increments.size() != bucket_counts_.size()) { - throw std::length_error("The size of bucket_increments was not equal to" - "the number of buckets in the histogram."); + throw std::length_error( + "The size of bucket_increments was not equal to" + "the number of buckets in the histogram."); } sum_.Increment(sum_of_values); for (std::size_t i{0}; i < bucket_counts_.size(); ++i) { - { bucket_counts_[i].Increment(bucket_increments[i]); } + { + bucket_counts_[i].Increment(bucket_increments[i]); + } } } diff --git a/core/tests/histogram_test.cc b/core/tests/histogram_test.cc index 23494edf..9e2793fb 100644 --- a/core/tests/histogram_test.cc +++ b/core/tests/histogram_test.cc @@ -105,8 +105,7 @@ TEST(HistogramTest, observe_multiple_test_length_error) { Histogram histogram{{1, 2}}; // 2 bucket boundaries means there are 3 buckets, so giving just 2 bucket // increments should result in a length_error. - ASSERT_THROW(histogram.ObserveMultiple({5, 9}, 20), - std::length_error); + ASSERT_THROW(histogram.ObserveMultiple({5, 9}, 20), std::length_error); } } // namespace diff --git a/core/tests/registry_test.cc b/core/tests/registry_test.cc index 652f54bc..7033567e 100644 --- a/core/tests/registry_test.cc +++ b/core/tests/registry_test.cc @@ -1,6 +1,6 @@ +#include "prometheus/registry.h" #include "prometheus/counter.h" #include "prometheus/histogram.h" -#include "prometheus/registry.h" #include diff --git a/pull/include/prometheus/detail/pull_export.h b/pull/include/prometheus/detail/pull_export.h index 92624749..7537ed0b 100644 --- a/pull/include/prometheus/detail/pull_export.h +++ b/pull/include/prometheus/detail/pull_export.h @@ -1,11 +1,11 @@ #pragma once #if defined(_WIN32) -# ifdef PROMETHEUS_CPP_COMPILE_PULL -# define PROMETHEUS_CPP_PULL_EXPORT __declspec(dllexport) -# else -# define PROMETHEUS_CPP_PULL_EXPORT __declspec(dllimport) -# endif +#ifdef PROMETHEUS_CPP_COMPILE_PULL +#define PROMETHEUS_CPP_PULL_EXPORT __declspec(dllexport) #else -# define PROMETHEUS_CPP_PULL_EXPORT __attribute__((visibility("default"))) +#define PROMETHEUS_CPP_PULL_EXPORT __declspec(dllimport) +#endif +#else +#define PROMETHEUS_CPP_PULL_EXPORT __attribute__((visibility("default"))) #endif diff --git a/pull/src/exposer.cc b/pull/src/exposer.cc index 6287c830..966d04ae 100644 --- a/pull/src/exposer.cc +++ b/pull/src/exposer.cc @@ -11,11 +11,11 @@ namespace prometheus { -Exposer::Exposer(const std::string& bind_address, const std::string& uri, const std::size_t num_threads) - : server_(new CivetServer{ - std::vector{ - "listening_ports", bind_address, - "num_threads", std::to_string(num_threads)}}), +Exposer::Exposer(const std::string& bind_address, const std::string& uri, + const std::size_t num_threads) + : server_(new CivetServer{std::vector{ + "listening_ports", bind_address, "num_threads", + std::to_string(num_threads)}}), exposer_registry_(std::make_shared()), metrics_handler_( new detail::MetricsHandler{collectables_, *exposer_registry_}), diff --git a/push/include/prometheus/detail/push_export.h b/push/include/prometheus/detail/push_export.h index fe714a2b..10aae6e2 100644 --- a/push/include/prometheus/detail/push_export.h +++ b/push/include/prometheus/detail/push_export.h @@ -1,11 +1,11 @@ #pragma once #if defined(_WIN32) -# ifdef PROMETHEUS_CPP_COMPILE_PUSH -# define PROMETHEUS_CPP_PUSH_EXPORT __declspec(dllexport) -# else -# define PROMETHEUS_CPP_PUSH_EXPORT __declspec(dllimport) -# endif +#ifdef PROMETHEUS_CPP_COMPILE_PUSH +#define PROMETHEUS_CPP_PUSH_EXPORT __declspec(dllexport) #else -# define PROMETHEUS_CPP_PUSH_EXPORT __attribute__((visibility("default"))) +#define PROMETHEUS_CPP_PUSH_EXPORT __declspec(dllimport) +#endif +#else +#define PROMETHEUS_CPP_PUSH_EXPORT __attribute__((visibility("default"))) #endif From c54cb06d043355e3108662febd46bc80f40d67f8 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 17 Oct 2019 18:14:02 +0200 Subject: [PATCH 042/206] chore(buildifier): Format everything --- pull/tests/integration/BUILD.bazel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pull/tests/integration/BUILD.bazel b/pull/tests/integration/BUILD.bazel index 84fdb4b6..4104a6a5 100644 --- a/pull/tests/integration/BUILD.bazel +++ b/pull/tests/integration/BUILD.bazel @@ -23,4 +23,4 @@ sh_test( "sample-server", ], tags = ["manual"], -) \ No newline at end of file +) From b68155af29ff42ae440c96652a95f46d80a59263 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Fri, 18 Oct 2019 09:26:26 +0200 Subject: [PATCH 043/206] chore: Simplify external templates --- core/CMakeLists.txt | 5 ++- core/include/prometheus/detail/builder.h | 3 +- core/include/prometheus/registry.h | 11 ++++++ core/src/counter.cc | 13 ------- .../src/detail/{builder.impl.h => builder.cc} | 18 ++++++++-- core/src/{family.impl.h => family.cc} | 12 +++++-- core/src/gauge.cc | 13 ------- core/src/histogram.cc | 13 ------- core/src/registry.cc | 35 +++++++++++++++++++ core/src/registry.impl.h | 17 --------- core/src/summary.cc | 13 ------- 11 files changed, 75 insertions(+), 78 deletions(-) rename core/src/detail/{builder.impl.h => builder.cc} (50%) rename core/src/{family.impl.h => family.cc} (87%) delete mode 100644 core/src/registry.impl.h diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index e2d18912..0685bfed 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -2,15 +2,14 @@ add_library(core src/check_names.cc src/counter.cc - src/detail/builder.impl.h + src/detail/builder.cc src/detail/ckms_quantiles.cc src/detail/time_window_quantiles.cc src/detail/utils.cc + src/family.cc src/gauge.cc - src/family.impl.h src/histogram.cc src/registry.cc - src/registry.impl.h src/serializer.cc src/summary.cc src/text_serializer.cc diff --git a/core/include/prometheus/detail/builder.h b/core/include/prometheus/detail/builder.h index e40a42f1..0278d993 100644 --- a/core/include/prometheus/detail/builder.h +++ b/core/include/prometheus/detail/builder.h @@ -3,12 +3,11 @@ #include #include -#include "prometheus/registry.h" - namespace prometheus { template class Family; +class Registry; namespace detail { diff --git a/core/include/prometheus/registry.h b/core/include/prometheus/registry.h index 69a0e4b4..4db0093d 100644 --- a/core/include/prometheus/registry.h +++ b/core/include/prometheus/registry.h @@ -14,6 +14,11 @@ namespace prometheus { +class Counter; +class Gauge; +class Histogram; +class Summary; + namespace detail { template @@ -35,6 +40,12 @@ class Builder; /// a data race. class PROMETHEUS_CPP_CORE_EXPORT Registry : public Collectable { public: + /// \brief name Create a new registry. + Registry(); + + /// \brief name Destroys a registry. + ~Registry(); + /// \brief Returns a list of metrics and their samples. /// /// Every time the Registry is scraped it calls each of the metrics Collect diff --git a/core/src/counter.cc b/core/src/counter.cc index 2aa5ba4b..fc5b6f30 100644 --- a/core/src/counter.cc +++ b/core/src/counter.cc @@ -1,9 +1,5 @@ #include "prometheus/counter.h" -#include "detail/builder.impl.h" -#include "family.impl.h" -#include "registry.impl.h" - namespace prometheus { void Counter::Increment() { gauge_.Increment(); } @@ -18,13 +14,4 @@ ClientMetric Counter::Collect() const { return metric; } -template class PROMETHEUS_CPP_CORE_EXPORT detail::Builder; -template class PROMETHEUS_CPP_CORE_EXPORT Family; - -template Family& Registry::Add( - const std::string& name, const std::string& help, - const std::map& labels); - -detail::Builder BuildCounter() { return {}; } - } // namespace prometheus diff --git a/core/src/detail/builder.impl.h b/core/src/detail/builder.cc similarity index 50% rename from core/src/detail/builder.impl.h rename to core/src/detail/builder.cc index 82ff9591..2d82ad0d 100644 --- a/core/src/detail/builder.impl.h +++ b/core/src/detail/builder.cc @@ -1,7 +1,11 @@ -#pragma once - #include "prometheus/detail/builder.h" +#include "prometheus/counter.h" +#include "prometheus/gauge.h" +#include "prometheus/histogram.h" +#include "prometheus/registry.h" +#include "prometheus/summary.h" + namespace prometheus { namespace detail { @@ -30,6 +34,16 @@ Family& Builder::Register(Registry& registry) { return registry.Add(name_, help_, labels_); } +template class PROMETHEUS_CPP_CORE_EXPORT Builder; +template class PROMETHEUS_CPP_CORE_EXPORT Builder; +template class PROMETHEUS_CPP_CORE_EXPORT Builder; +template class PROMETHEUS_CPP_CORE_EXPORT Builder; + } // namespace detail +detail::Builder BuildCounter() { return {}; } +detail::Builder BuildGauge() { return {}; } +detail::Builder BuildHistogram() { return {}; } +detail::Builder BuildSummary() { return {}; } + } // namespace prometheus diff --git a/core/src/family.impl.h b/core/src/family.cc similarity index 87% rename from core/src/family.impl.h rename to core/src/family.cc index 0c1f07b8..851fa785 100644 --- a/core/src/family.impl.h +++ b/core/src/family.cc @@ -1,7 +1,10 @@ -#pragma once - #include "prometheus/family.h" +#include "prometheus/counter.h" +#include "prometheus/gauge.h" +#include "prometheus/histogram.h" +#include "prometheus/summary.h" + namespace prometheus { template @@ -84,4 +87,9 @@ ClientMetric Family::CollectMetric(std::size_t hash, T* metric) { return collected; } +template class PROMETHEUS_CPP_CORE_EXPORT Family; +template class PROMETHEUS_CPP_CORE_EXPORT Family; +template class PROMETHEUS_CPP_CORE_EXPORT Family; +template class PROMETHEUS_CPP_CORE_EXPORT Family; + } // namespace prometheus diff --git a/core/src/gauge.cc b/core/src/gauge.cc index cba54025..05651b41 100644 --- a/core/src/gauge.cc +++ b/core/src/gauge.cc @@ -1,9 +1,5 @@ #include "prometheus/gauge.h" -#include "detail/builder.impl.h" -#include "family.impl.h" -#include "registry.impl.h" - #include namespace prometheus { @@ -49,13 +45,4 @@ ClientMetric Gauge::Collect() const { return metric; } -template class PROMETHEUS_CPP_CORE_EXPORT Family; -template class PROMETHEUS_CPP_CORE_EXPORT detail::Builder; - -template Family& Registry::Add( - const std::string& name, const std::string& help, - const std::map& labels); - -detail::Builder BuildGauge() { return {}; } - } // namespace prometheus diff --git a/core/src/histogram.cc b/core/src/histogram.cc index 703acaf5..a1c4df00 100644 --- a/core/src/histogram.cc +++ b/core/src/histogram.cc @@ -1,9 +1,5 @@ #include "prometheus/histogram.h" -#include "detail/builder.impl.h" -#include "family.impl.h" -#include "registry.impl.h" - #include #include #include @@ -64,13 +60,4 @@ ClientMetric Histogram::Collect() const { return metric; } -template class PROMETHEUS_CPP_CORE_EXPORT Family; -template class PROMETHEUS_CPP_CORE_EXPORT detail::Builder; - -template Family& Registry::Add( - const std::string& name, const std::string& help, - const std::map& labels); - -detail::Builder BuildHistogram() { return {}; } - } // namespace prometheus diff --git a/core/src/registry.cc b/core/src/registry.cc index 24627679..c94dda89 100644 --- a/core/src/registry.cc +++ b/core/src/registry.cc @@ -1,9 +1,18 @@ #include "prometheus/registry.h" +#include "prometheus/counter.h" +#include "prometheus/gauge.h" +#include "prometheus/histogram.h" +#include "prometheus/summary.h" + #include namespace prometheus { +Registry::Registry() = default; + +Registry::~Registry() = default; + std::vector Registry::Collect() { std::lock_guard lock{mutex_}; auto results = std::vector{}; @@ -16,4 +25,30 @@ std::vector Registry::Collect() { return results; } +template +Family& Registry::Add(const std::string& name, const std::string& help, + const std::map& labels) { + std::lock_guard lock{mutex_}; + auto family = detail::make_unique>(name, help, labels); + auto& ref = *family; + collectables_.push_back(std::move(family)); + return ref; +} + +template Family& Registry::Add( + const std::string& name, const std::string& help, + const std::map& labels); + +template Family& Registry::Add( + const std::string& name, const std::string& help, + const std::map& labels); + +template Family& Registry::Add( + const std::string& name, const std::string& help, + const std::map& labels); + +template Family& Registry::Add( + const std::string& name, const std::string& help, + const std::map& labels); + } // namespace prometheus diff --git a/core/src/registry.impl.h b/core/src/registry.impl.h deleted file mode 100644 index 353280e1..00000000 --- a/core/src/registry.impl.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "prometheus/registry.h" - -namespace prometheus { - -template -Family& Registry::Add(const std::string& name, const std::string& help, - const std::map& labels) { - std::lock_guard lock{mutex_}; - auto family = detail::make_unique>(name, help, labels); - auto& ref = *family; - collectables_.push_back(std::move(family)); - return ref; -} - -} // namespace prometheus diff --git a/core/src/summary.cc b/core/src/summary.cc index 1504b264..2d913aa2 100644 --- a/core/src/summary.cc +++ b/core/src/summary.cc @@ -1,9 +1,5 @@ #include "prometheus/summary.h" -#include "detail/builder.impl.h" -#include "family.impl.h" -#include "registry.impl.h" - namespace prometheus { Summary::Summary(const Quantiles& quantiles, @@ -38,13 +34,4 @@ ClientMetric Summary::Collect() { return metric; } -template class PROMETHEUS_CPP_CORE_EXPORT Family; -template class PROMETHEUS_CPP_CORE_EXPORT detail::Builder; - -template Family& Registry::Add( - const std::string& name, const std::string& help, - const std::map& labels); - -detail::Builder BuildSummary() { return {}; } - } // namespace prometheus From 5a3ee66c7e72deb1b9d5ebe72914f8ff5741d433 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Fri, 18 Oct 2019 21:52:11 +0200 Subject: [PATCH 044/206] fix(symbols): Fix Windows and Bazel symbol visibility --- CMakeLists.txt | 1 + bazel/BUILD.bazel | 5 ++++- bazel/dummy_export.h.tpl | 4 ++++ bazel/export_header.bzl | 21 ++++++++++++++++++++ core/BUILD.bazel | 13 ++++++++---- core/CMakeLists.txt | 10 ++++++++-- core/include/prometheus/detail/core_export.h | 11 ---------- pull/BUILD.bazel | 11 ++++++++-- pull/CMakeLists.txt | 10 ++++++++-- pull/include/prometheus/detail/pull_export.h | 11 ---------- push/BUILD.bazel | 13 ++++++++---- push/CMakeLists.txt | 10 ++++++++-- push/include/prometheus/detail/push_export.h | 11 ---------- 13 files changed, 81 insertions(+), 50 deletions(-) create mode 100644 bazel/dummy_export.h.tpl create mode 100644 bazel/export_header.bzl delete mode 100644 core/include/prometheus/detail/core_export.h delete mode 100644 pull/include/prometheus/detail/pull_export.h delete mode 100644 push/include/prometheus/detail/push_export.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0713a8fd..28e193f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.5 FATAL_ERROR) project(prometheus-cpp VERSION 0.8.0) +include(GenerateExportHeader) include(GNUInstallDirs) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") diff --git a/bazel/BUILD.bazel b/bazel/BUILD.bazel index a9f760ac..271eb33a 100644 --- a/bazel/BUILD.bazel +++ b/bazel/BUILD.bazel @@ -1,4 +1,7 @@ exports_files( - glob(["*.BUILD"]), + glob([ + "*.BUILD", + "*.tpl", + ]), visibility = ["//visibility:public"], ) diff --git a/bazel/dummy_export.h.tpl b/bazel/dummy_export.h.tpl new file mode 100644 index 00000000..84c44eff --- /dev/null +++ b/bazel/dummy_export.h.tpl @@ -0,0 +1,4 @@ +#pragma once + +#define {BASE_NAME}_EXPORT +#define {BASE_NAME}_NO_EXPORT diff --git a/bazel/export_header.bzl b/bazel/export_header.bzl new file mode 100644 index 00000000..4637562a --- /dev/null +++ b/bazel/export_header.bzl @@ -0,0 +1,21 @@ +def _generate_dummy_export_header_impl(ctx): + ctx.actions.expand_template( + template = ctx.file._template, + output = ctx.outputs.header_file, + substitutions = { + "{BASE_NAME}": ctx.attr.basename, + }, + ) + +generate_dummy_export_header = rule( + attrs = { + "basename": attr.string(mandatory = True), + "header": attr.string(mandatory = True), + "_template": attr.label( + allow_single_file = True, + default = Label("@com_github_jupp0r_prometheus_cpp//bazel:dummy_export.h.tpl"), + ), + }, + implementation = _generate_dummy_export_header_impl, + outputs = {"header_file": "%{header}"}, +) diff --git a/core/BUILD.bazel b/core/BUILD.bazel index b1eb862f..a302f195 100644 --- a/core/BUILD.bazel +++ b/core/BUILD.bazel @@ -1,3 +1,11 @@ +load("//bazel:export_header.bzl", "generate_dummy_export_header") + +generate_dummy_export_header( + name = "export_header", + basename = "PROMETHEUS_CPP_CORE", + header = "include/prometheus/detail/core_export.h", +) + cc_library( name = "core", srcs = glob([ @@ -6,10 +14,7 @@ cc_library( ]), hdrs = glob( ["include/**/*.h"], - ), - local_defines = [ - "PROMETHEUS_CPP_COMPILE_CORE", - ], + ) + [":export_header"], strip_include_prefix = "include", visibility = ["//visibility:public"], ) diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 0685bfed..dad457e7 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -26,16 +26,22 @@ target_link_libraries(core target_include_directories(core PUBLIC $ + $ ) set_target_properties(core PROPERTIES OUTPUT_NAME ${PROJECT_NAME}-core - DEFINE_SYMBOL PROMETHEUS_CPP_COMPILE_CORE + DEFINE_SYMBOL PROMETHEUS_CPP_CORE_EXPORTS VERSION "${PROJECT_VERSION}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}" ) +generate_export_header(core + BASE_NAME ${PROJECT_NAME}-core + EXPORT_FILE_NAME include/prometheus/detail/core_export.h +) + install( TARGETS core EXPORT ${PROJECT_NAME}-targets @@ -46,7 +52,7 @@ install( ) install( - DIRECTORY include/ + DIRECTORY include/ ${CMAKE_CURRENT_BINARY_DIR}/include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) diff --git a/core/include/prometheus/detail/core_export.h b/core/include/prometheus/detail/core_export.h deleted file mode 100644 index 8517f9b2..00000000 --- a/core/include/prometheus/detail/core_export.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#if defined(_WIN32) -#ifdef PROMETHEUS_CPP_COMPILE_CORE -#define PROMETHEUS_CPP_CORE_EXPORT __declspec(dllexport) -#else -#define PROMETHEUS_CPP_CORE_EXPORT __declspec(dllimport) -#endif -#else -#define PROMETHEUS_CPP_CORE_EXPORT __attribute__((visibility("default"))) -#endif diff --git a/pull/BUILD.bazel b/pull/BUILD.bazel index c0c1e582..6d90c233 100644 --- a/pull/BUILD.bazel +++ b/pull/BUILD.bazel @@ -1,3 +1,11 @@ +load("//bazel:export_header.bzl", "generate_dummy_export_header") + +generate_dummy_export_header( + name = "export_header", + basename = "PROMETHEUS_CPP_PULL", + header = "include/prometheus/detail/pull_export.h", +) + cc_library( name = "pull", srcs = glob([ @@ -6,10 +14,9 @@ cc_library( ]), hdrs = glob( ["include/**/*.h"], - ), + ) + [":export_header"], local_defines = [ "HAVE_ZLIB", - "PROMETHEUS_CPP_COMPILE_PULL", ], strip_include_prefix = "include", visibility = ["//visibility:public"], diff --git a/pull/CMakeLists.txt b/pull/CMakeLists.txt index 29ae695e..c940e5fe 100644 --- a/pull/CMakeLists.txt +++ b/pull/CMakeLists.txt @@ -31,6 +31,7 @@ target_link_libraries(pull target_include_directories(pull PUBLIC $ + $ PRIVATE ${CIVETWEB_INCLUDE_DIRS} ) @@ -43,11 +44,16 @@ target_compile_definitions(pull set_target_properties(pull PROPERTIES OUTPUT_NAME ${PROJECT_NAME}-pull - DEFINE_SYMBOL PROMETHEUS_CPP_COMPILE_PULL + DEFINE_SYMBOL PROMETHEUS_CPP_PULL_EXPORTS VERSION "${PROJECT_VERSION}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}" ) +generate_export_header(pull + BASE_NAME ${PROJECT_NAME}-pull + EXPORT_FILE_NAME include/prometheus/detail/pull_export.h +) + install( TARGETS pull EXPORT ${PROJECT_NAME}-targets @@ -58,7 +64,7 @@ install( ) install( - DIRECTORY include/ + DIRECTORY include/ ${CMAKE_CURRENT_BINARY_DIR}/include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) diff --git a/pull/include/prometheus/detail/pull_export.h b/pull/include/prometheus/detail/pull_export.h deleted file mode 100644 index 7537ed0b..00000000 --- a/pull/include/prometheus/detail/pull_export.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#if defined(_WIN32) -#ifdef PROMETHEUS_CPP_COMPILE_PULL -#define PROMETHEUS_CPP_PULL_EXPORT __declspec(dllexport) -#else -#define PROMETHEUS_CPP_PULL_EXPORT __declspec(dllimport) -#endif -#else -#define PROMETHEUS_CPP_PULL_EXPORT __attribute__((visibility("default"))) -#endif diff --git a/push/BUILD.bazel b/push/BUILD.bazel index 7bcb446d..c7cb3f91 100644 --- a/push/BUILD.bazel +++ b/push/BUILD.bazel @@ -1,3 +1,11 @@ +load("//bazel:export_header.bzl", "generate_dummy_export_header") + +generate_dummy_export_header( + name = "export_header", + basename = "PROMETHEUS_CPP_PUSH", + header = "include/prometheus/detail/push_export.h", +) + cc_library( name = "push", srcs = glob([ @@ -6,15 +14,12 @@ cc_library( ]), hdrs = glob( ["include/**/*.h"], - ), + ) + [":export_header"], linkopts = select({ "//:windows": [], "//:windows_msvc": [], "//conditions:default": ["-lpthread"], }), - local_defines = [ - "PROMETHEUS_CPP_COMPILE_PUSH", - ], strip_include_prefix = "include", visibility = ["//visibility:public"], deps = [ diff --git a/push/CMakeLists.txt b/push/CMakeLists.txt index b62b473e..721386d1 100644 --- a/push/CMakeLists.txt +++ b/push/CMakeLists.txt @@ -19,6 +19,7 @@ target_link_libraries(push target_include_directories(push PUBLIC $ + $ PRIVATE ${CURL_INCLUDE_DIRS} ) @@ -26,11 +27,16 @@ target_include_directories(push set_target_properties(push PROPERTIES OUTPUT_NAME ${PROJECT_NAME}-push - DEFINE_SYMBOL PROMETHEUS_CPP_COMPILE_PUSH + DEFINE_SYMBOL PROMETHEUS_CPP_PUSH_EXPORTS VERSION "${PROJECT_VERSION}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}" ) +generate_export_header(push + BASE_NAME ${PROJECT_NAME}-push + EXPORT_FILE_NAME include/prometheus/detail/push_export.h +) + install( TARGETS push EXPORT ${PROJECT_NAME}-targets @@ -41,7 +47,7 @@ install( ) install( - DIRECTORY include/ + DIRECTORY include/ ${CMAKE_CURRENT_BINARY_DIR}/include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) diff --git a/push/include/prometheus/detail/push_export.h b/push/include/prometheus/detail/push_export.h deleted file mode 100644 index 10aae6e2..00000000 --- a/push/include/prometheus/detail/push_export.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#if defined(_WIN32) -#ifdef PROMETHEUS_CPP_COMPILE_PUSH -#define PROMETHEUS_CPP_PUSH_EXPORT __declspec(dllexport) -#else -#define PROMETHEUS_CPP_PUSH_EXPORT __declspec(dllimport) -#endif -#else -#define PROMETHEUS_CPP_PUSH_EXPORT __attribute__((visibility("default"))) -#endif From ae5f98dd94d4367cba15a6d2bb56d01d40e185d6 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Fri, 18 Oct 2019 23:50:30 +0200 Subject: [PATCH 045/206] Use civetweb snapshot This works around civetweb/civetweb#663 --- repositories.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/repositories.bzl b/repositories.bzl index 8696657b..92ea3b14 100644 --- a/repositories.bzl +++ b/repositories.bzl @@ -3,10 +3,10 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") def load_civetweb(): http_archive( name = "civetweb", - strip_prefix = "civetweb-1.11", - sha256 = "de7d5e7a2d9551d325898c71e41d437d5f7b51e754b242af897f7be96e713a42", + strip_prefix = "civetweb-2c1caa6e690bfe3b435a10c372ab2dcd14b872e8", + sha256 = "d576b2257fe116523e5644232868670dcdd6c89b8e42b69d51e26b146575ab6a", urls = [ - "https://github.com/civetweb/civetweb/archive/v1.11.tar.gz", + "https://github.com/civetweb/civetweb/archive/2c1caa6e690bfe3b435a10c372ab2dcd14b872e8.tar.gz", ], build_file = "@com_github_jupp0r_prometheus_cpp//bazel:civetweb.BUILD", ) From c57ae5728f914382b0903b03bdca6055cdcebd94 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Fri, 25 Oct 2019 10:27:29 +0200 Subject: [PATCH 046/206] fix(core): Make registry insert behavior configurable Add three different insert strategies for the Registry. The `NonStandardAppend` is only there and selected for backward compatibility and most likely will go away in the future. --- core/include/prometheus/family.h | 10 +++ core/include/prometheus/registry.h | 33 ++++++++- core/src/family.cc | 10 +++ core/src/registry.cc | 112 +++++++++++++++++++++++++++-- core/tests/registry_test.cc | 101 +++++++++++++++++++++++++- 5 files changed, 255 insertions(+), 11 deletions(-) diff --git a/core/include/prometheus/family.h b/core/include/prometheus/family.h index 44b3c98b..b047f3ea 100644 --- a/core/include/prometheus/family.h +++ b/core/include/prometheus/family.h @@ -118,6 +118,16 @@ class PROMETHEUS_CPP_CORE_EXPORT Family : public Collectable { /// if the given metric was not returned by Add(). void Remove(T* metric); + /// \brief Returns the name for this family. + /// + /// \return The family name. + const std::string& GetName() const; + + /// \brief Returns the constant labels for this family. + /// + /// \return All constant labels as key-value pairs. + const std::map GetConstantLabels() const; + /// \brief Returns the current value of each dimensional data. /// /// Collect is called by the Registry when collecting metrics. diff --git a/core/include/prometheus/registry.h b/core/include/prometheus/registry.h index 4db0093d..bef7d924 100644 --- a/core/include/prometheus/registry.h +++ b/core/include/prometheus/registry.h @@ -40,8 +40,27 @@ class Builder; /// a data race. class PROMETHEUS_CPP_CORE_EXPORT Registry : public Collectable { public: + /// \brief How to deal with repeatedly added family names for a type. + /// + /// Adding a family with the same name but different types is always an error + /// and will lead to an exception. + enum class InsertBehavior { + /// \brief If a family with the same name and labels already exists return + /// the existing one. If no family with that name exists create it. + /// Otherwise throw. + Merge, + /// \brief Throws if a family with the same name already exists. + Throw, + /// \brief Never merge and always create a new family. This violates the + /// prometheus specification but was the default behavior in earlier + /// versions + NonStandardAppend, + }; + /// \brief name Create a new registry. - Registry(); + /// + /// \param insert_behavior How to handle families with the same name. + explicit Registry(InsertBehavior insert_behavior = InsertBehavior::Merge); /// \brief name Destroys a registry. ~Registry(); @@ -58,11 +77,21 @@ class PROMETHEUS_CPP_CORE_EXPORT Registry : public Collectable { template friend class detail::Builder; + template + std::vector>>& GetFamilies(); + + template + bool NameExistsInOtherType(const std::string& name) const; + template Family& Add(const std::string& name, const std::string& help, const std::map& labels); - std::vector> collectables_; + const InsertBehavior insert_behavior_; + std::vector>> counters_; + std::vector>> gauges_; + std::vector>> histograms_; + std::vector>> summaries_; std::mutex mutex_; }; diff --git a/core/src/family.cc b/core/src/family.cc index 851fa785..a9a9af9b 100644 --- a/core/src/family.cc +++ b/core/src/family.cc @@ -58,6 +58,16 @@ void Family::Remove(T* metric) { labels_reverse_lookup_.erase(metric); } +template +const std::string& Family::GetName() const { + return name_; +} + +template +const std::map Family::GetConstantLabels() const { + return constant_labels_; +} + template std::vector Family::Collect() { std::lock_guard lock{mutex_}; diff --git a/core/src/registry.cc b/core/src/registry.cc index c94dda89..59084ed1 100644 --- a/core/src/registry.cc +++ b/core/src/registry.cc @@ -9,29 +9,127 @@ namespace prometheus { -Registry::Registry() = default; +namespace { +template +void CollectAll(std::vector& results, const T& families) { + for (auto&& collectable : families) { + auto metrics = collectable->Collect(); + results.insert(results.end(), std::make_move_iterator(metrics.begin()), + std::make_move_iterator(metrics.end())); + } +} + +bool FamilyNameExists(const std::string& /* name */) { return false; } + +template +bool FamilyNameExists(const std::string& name, const T& families, + Args&&... args) { + auto sameName = [&name](const typename T::value_type& entry) { + return name == entry->GetName(); + }; + auto exists = std::find_if(std::begin(families), std::end(families), + sameName) != std::end(families); + return exists || FamilyNameExists(name, args...); +} +} // namespace + +Registry::Registry(InsertBehavior insert_behavior) + : insert_behavior_{insert_behavior} {} Registry::~Registry() = default; std::vector Registry::Collect() { std::lock_guard lock{mutex_}; auto results = std::vector{}; - for (auto&& collectable : collectables_) { - auto metrics = collectable->Collect(); - results.insert(results.end(), std::make_move_iterator(metrics.begin()), - std::make_move_iterator(metrics.end())); - } + + CollectAll(results, counters_); + CollectAll(results, gauges_); + CollectAll(results, histograms_); + CollectAll(results, summaries_); return results; } +template <> +std::vector>>& Registry::GetFamilies() { + return counters_; +} + +template <> +std::vector>>& Registry::GetFamilies() { + return gauges_; +} + +template <> +std::vector>>& Registry::GetFamilies() { + return histograms_; +} + +template <> +std::vector>>& Registry::GetFamilies() { + return summaries_; +} + +template <> +bool Registry::NameExistsInOtherType(const std::string& name) const { + return FamilyNameExists(name, gauges_, histograms_, summaries_); +} + +template <> +bool Registry::NameExistsInOtherType(const std::string& name) const { + return FamilyNameExists(name, counters_, histograms_, summaries_); +} + +template <> +bool Registry::NameExistsInOtherType(const std::string& name) const { + return FamilyNameExists(name, counters_, gauges_, summaries_); +} + +template <> +bool Registry::NameExistsInOtherType(const std::string& name) const { + return FamilyNameExists(name, counters_, gauges_, histograms_); +} + template Family& Registry::Add(const std::string& name, const std::string& help, const std::map& labels) { std::lock_guard lock{mutex_}; + + if (NameExistsInOtherType(name)) { + throw std::invalid_argument( + "Family name already exists with different type"); + } + + auto& families = GetFamilies(); + + if (insert_behavior_ == InsertBehavior::Merge) { + auto same_name_and_labels = + [&name, &labels](const std::unique_ptr>& family) { + return std::tie(name, labels) == + std::tie(family->GetName(), family->GetConstantLabels()); + }; + + auto it = + std::find_if(families.begin(), families.end(), same_name_and_labels); + if (it != families.end()) { + return **it; + } + } + + if (insert_behavior_ != InsertBehavior::NonStandardAppend) { + auto same_name = [&name](const std::unique_ptr>& family) { + return name == family->GetName(); + }; + + auto it = std::find_if(families.begin(), families.end(), same_name); + if (it != families.end()) { + throw std::invalid_argument("Family name already exists"); + } + } + auto family = detail::make_unique>(name, help, labels); auto& ref = *family; - collectables_.push_back(std::move(family)); + families.push_back(std::move(family)); return ref; } diff --git a/core/tests/registry_test.cc b/core/tests/registry_test.cc index 7033567e..5fb4a041 100644 --- a/core/tests/registry_test.cc +++ b/core/tests/registry_test.cc @@ -1,13 +1,12 @@ #include "prometheus/registry.h" #include "prometheus/counter.h" #include "prometheus/histogram.h" +#include "prometheus/summary.h" #include #include -#include "prometheus/collectable.h" - namespace prometheus { namespace { @@ -39,5 +38,103 @@ TEST(RegistryTest, build_histogram_family) { ASSERT_EQ(collected.size(), 1U); } +TEST(RegistryTest, reject_different_type_than_counter) { + const auto same_name = std::string{"same_name"}; + Registry registry{}; + + EXPECT_NO_THROW(BuildCounter().Name(same_name).Register(registry)); + EXPECT_ANY_THROW(BuildGauge().Name(same_name).Register(registry)); + EXPECT_ANY_THROW(BuildHistogram().Name(same_name).Register(registry)); + EXPECT_ANY_THROW(BuildSummary().Name(same_name).Register(registry)); +} + +TEST(RegistryTest, reject_different_type_than_gauge) { + const auto same_name = std::string{"same_name"}; + Registry registry{}; + + EXPECT_NO_THROW(BuildGauge().Name(same_name).Register(registry)); + EXPECT_ANY_THROW(BuildCounter().Name(same_name).Register(registry)); + EXPECT_ANY_THROW(BuildHistogram().Name(same_name).Register(registry)); + EXPECT_ANY_THROW(BuildSummary().Name(same_name).Register(registry)); +} + +TEST(RegistryTest, reject_different_type_than_histogram) { + const auto same_name = std::string{"same_name"}; + Registry registry{}; + + EXPECT_NO_THROW(BuildHistogram().Name(same_name).Register(registry)); + EXPECT_ANY_THROW(BuildCounter().Name(same_name).Register(registry)); + EXPECT_ANY_THROW(BuildGauge().Name(same_name).Register(registry)); + EXPECT_ANY_THROW(BuildSummary().Name(same_name).Register(registry)); +} + +TEST(RegistryTest, reject_different_type_than_summary) { + const auto same_name = std::string{"same_name"}; + Registry registry{}; + + EXPECT_NO_THROW(BuildSummary().Name(same_name).Register(registry)); + EXPECT_ANY_THROW(BuildCounter().Name(same_name).Register(registry)); + EXPECT_ANY_THROW(BuildGauge().Name(same_name).Register(registry)); + EXPECT_ANY_THROW(BuildHistogram().Name(same_name).Register(registry)); +} + +TEST(RegistryTest, append_same_families) { + Registry registry{Registry::InsertBehavior::NonStandardAppend}; + + std::size_t loops = 4; + + while (loops-- > 0) { + BuildCounter() + .Name("counter") + .Help("Test Counter") + .Register(registry) + .Add({{"name", "test_counter"}}); + } + + auto collected = registry.Collect(); + EXPECT_EQ(4U, collected.size()); +} + +TEST(RegistryTest, throw_for_same_family_name) { + const auto same_name = std::string{"same_name"}; + Registry registry{Registry::InsertBehavior::Throw}; + + EXPECT_NO_THROW(BuildCounter().Name(same_name).Register(registry)); + EXPECT_ANY_THROW(BuildCounter().Name(same_name).Register(registry)); +} + +TEST(RegistryTest, merge_same_families) { + Registry registry{Registry::InsertBehavior::Merge}; + + std::size_t loops = 4; + + while (loops-- > 0) { + BuildCounter() + .Name("counter") + .Help("Test Counter") + .Register(registry) + .Add({{"name", "test_counter"}}); + } + + auto collected = registry.Collect(); + EXPECT_EQ(1U, collected.size()); +} + +TEST(RegistryTest, do_not_merge_families_with_different_labels) { + Registry registry{Registry::InsertBehavior::Merge}; + + EXPECT_NO_THROW(BuildCounter() + .Name("counter") + .Help("Test Counter") + .Labels({{"a", "A"}}) + .Register(registry)); + + EXPECT_ANY_THROW(BuildCounter() + .Name("counter") + .Help("Test Counter") + .Labels({{"b", "B"}}) + .Register(registry)); +} + } // namespace } // namespace prometheus From 7ad4101b39c6cc5791abff6a7a5aa76b22cc2641 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Fri, 25 Oct 2019 10:42:09 +0200 Subject: [PATCH 047/206] chore(doc): Add GitHub CI badge --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 918262fb..be8e6836 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,9 @@ -# Prometheus Client Library for Modern C++ [![Build Status](https://travis-ci.org/jupp0r/prometheus-cpp.svg?branch=master)](https://travis-ci.org/jupp0r/prometheus-cpp)[![Coverage Status](https://coveralls.io/repos/github/jupp0r/prometheus-cpp/badge.svg?branch=master)](https://coveralls.io/github/jupp0r/prometheus-cpp?branch=master)[![Coverity Scan](https://scan.coverity.com/projects/10567/badge.svg)](https://scan.coverity.com/projects/jupp0r-prometheus-cpp) +# Prometheus Client Library for Modern C++ + +[![CI Status](https://github.com/jupp0r/prometheus-cpp/workflows/Continuous%20Integration/badge.svg)](https://github.com/jupp0r/prometheus-cpp/actions?workflow=Continuous+Integration) +[![Travis Status](https://travis-ci.org/jupp0r/prometheus-cpp.svg?branch=master)](https://travis-ci.org/jupp0r/prometheus-cpp) +[![Coverage Status](https://coveralls.io/repos/github/jupp0r/prometheus-cpp/badge.svg?branch=master)](https://coveralls.io/github/jupp0r/prometheus-cpp?branch=master) +[![Coverity Scan](https://scan.coverity.com/projects/10567/badge.svg)](https://scan.coverity.com/projects/jupp0r-prometheus-cpp) This library aims to enable [Metrics-Driven Development](https://sookocheff.com/post/mdd/mdd/) for From 64528601721d2bae1f5772bcd3f741c8d689e371 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Tue, 29 Oct 2019 09:42:34 +0100 Subject: [PATCH 048/206] chore(bazel): Use maybe function from bazel_tools --- repositories.bzl | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/repositories.bzl b/repositories.bzl index 92ea3b14..ea154b17 100644 --- a/repositories.bzl +++ b/repositories.bzl @@ -1,7 +1,9 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") -def load_civetweb(): - http_archive( +def prometheus_cpp_repositories(): + maybe( + http_archive, name = "civetweb", strip_prefix = "civetweb-2c1caa6e690bfe3b435a10c372ab2dcd14b872e8", sha256 = "d576b2257fe116523e5644232868670dcdd6c89b8e42b69d51e26b146575ab6a", @@ -11,8 +13,8 @@ def load_civetweb(): build_file = "@com_github_jupp0r_prometheus_cpp//bazel:civetweb.BUILD", ) -def load_com_google_googletest(): - http_archive( + maybe( + http_archive, name = "com_google_googletest", sha256 = "9bf1fe5182a604b4135edc1a425ae356c9ad15e9b23f9f12a02e80184c3a249c", strip_prefix = "googletest-release-1.8.1", @@ -21,8 +23,8 @@ def load_com_google_googletest(): ], ) -def load_com_github_curl(): - http_archive( + maybe( + http_archive, name = "com_github_curl", sha256 = "e9c37986337743f37fd14fe8737f246e97aec94b39d1b71e8a5973f72a9fc4f5", strip_prefix = "curl-7.60.0", @@ -33,8 +35,8 @@ def load_com_github_curl(): build_file = "@com_github_jupp0r_prometheus_cpp//bazel:curl.BUILD", ) -def load_com_github_google_benchmark(): - http_archive( + maybe( + http_archive, name = "com_github_google_benchmark", sha256 = "f8e525db3c42efc9c7f3bc5176a8fa893a9a9920bbd08cef30fb56a51854d60d", strip_prefix = "benchmark-1.4.1", @@ -43,8 +45,8 @@ def load_com_github_google_benchmark(): ], ) -def load_net_zlib_zlib(): - http_archive( + maybe( + http_archive, name = "net_zlib_zlib", sha256 = "c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1", strip_prefix = "zlib-1.2.11", @@ -54,10 +56,3 @@ def load_net_zlib_zlib(): ], build_file = "@com_github_jupp0r_prometheus_cpp//bazel:zlib.BUILD", ) - -def prometheus_cpp_repositories(): - if "civetweb" not in native.existing_rules(): load_civetweb() - if "com_google_googletest" not in native.existing_rules(): load_com_google_googletest() - if "com_github_google_benchmark" not in native.existing_rules(): load_com_github_google_benchmark() - if "com_github_curl" not in native.existing_rules(): load_com_github_curl() - if "net_zlib_zlib" not in native.existing_rules(): load_net_zlib_zlib() From 01d635ea994ab6a111eec9f86699dcec247a2023 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Tue, 29 Oct 2019 10:25:48 +0100 Subject: [PATCH 049/206] chore(bazel): curl must not expect stropts.h header on Linux --- bazel/curl.bzl | 1 - 1 file changed, 1 deletion(-) diff --git a/bazel/curl.bzl b/bazel/curl.bzl index f1cbf10f..076f667b 100644 --- a/bazel/curl.bzl +++ b/bazel/curl.bzl @@ -182,7 +182,6 @@ BASE_CURL_COPTS = [ LINUX_CURL_COPTS = [ "-DHAVE_LINUX_TCP_H=1", "-DHAVE_MSG_NOSIGNAL=1", - "-DHAVE_STROPTS_H=1", ] CURL_COPTS = select({ From b9225b3a8c117ca5da2662559a20f7b2409855ae Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Tue, 29 Oct 2019 10:44:52 +0100 Subject: [PATCH 050/206] chore(curl): Use curl 7.66.0 --- repositories.bzl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/repositories.bzl b/repositories.bzl index ea154b17..258b73ff 100644 --- a/repositories.bzl +++ b/repositories.bzl @@ -26,11 +26,11 @@ def prometheus_cpp_repositories(): maybe( http_archive, name = "com_github_curl", - sha256 = "e9c37986337743f37fd14fe8737f246e97aec94b39d1b71e8a5973f72a9fc4f5", - strip_prefix = "curl-7.60.0", + sha256 = "d0393da38ac74ffac67313072d7fe75b1fa1010eb5987f63f349b024a36b7ffb", + strip_prefix = "curl-7.66.0", urls = [ - "https://mirror.bazel.build/curl.haxx.se/download/curl-7.60.0.tar.gz", - "https://curl.haxx.se/download/curl-7.60.0.tar.gz", + "https://github.com/curl/curl/releases/download/curl-7_66_0/curl-7.66.0.tar.gz", + "https://curl.haxx.se/download/curl-7.66.0.tar.gz", ], build_file = "@com_github_jupp0r_prometheus_cpp//bazel:curl.BUILD", ) From 1533c143744dc1d964aee38586ab293cee0516f1 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Tue, 29 Oct 2019 10:55:45 +0100 Subject: [PATCH 051/206] chore(bazel): Move repositories.bzl to bazel subdir --- WORKSPACE | 2 +- repositories.bzl => bazel/repositories.bzl | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename repositories.bzl => bazel/repositories.bzl (100%) diff --git a/WORKSPACE b/WORKSPACE index ee0a24fa..a7b4172e 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -1,5 +1,5 @@ workspace(name = "com_github_jupp0r_prometheus_cpp") -load(":repositories.bzl", "prometheus_cpp_repositories") +load("//bazel:repositories.bzl", "prometheus_cpp_repositories") prometheus_cpp_repositories() diff --git a/repositories.bzl b/bazel/repositories.bzl similarity index 100% rename from repositories.bzl rename to bazel/repositories.bzl From bfeb3459c1c4939252a1aa0b3229e96433b3a342 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Fri, 1 Nov 2019 13:11:54 +0100 Subject: [PATCH 052/206] feat(coverage): Use GitHub Actions for code coverage --- .github/scripts/run-cmake-coverage | 20 ++++++++++++++++++++ .github/scripts/run-cmake-test | 12 ++---------- .github/scripts/run-prepare | 2 +- .github/workflows/coverage.yml | 21 +++++++++++++++++++++ .travis.yml | 18 ------------------ 5 files changed, 44 insertions(+), 29 deletions(-) create mode 100755 .github/scripts/run-cmake-coverage create mode 100644 .github/workflows/coverage.yml diff --git a/.github/scripts/run-cmake-coverage b/.github/scripts/run-cmake-coverage new file mode 100755 index 00000000..492216df --- /dev/null +++ b/.github/scripts/run-cmake-coverage @@ -0,0 +1,20 @@ +#!/bin/bash + +set -euo pipefail + +WORKSPACE=$(cd "$(dirname "${BASH_SOURCE[0]}")"/../.. && /bin/pwd -P) +PATH=$HOME/.local/bin:$PATH + +pip install --user cpp-coveralls + +# Build with coverage + +mkdir "${WORKSPACE}/_build_coverage" && cd $_ +CFLAGS="--coverage" CXXFLAGS="--coverage" LDFLAGS="--coverage" cmake .. +make -j$(nproc) +ctest -V -LE Benchmark + +# Collect coverage data + +export TRAVIS_BRANCH=${GITHUB_REF} +coveralls --root .. --build-root . --gcov-options '\-lp' -E ".*/3rdparty/.*" -E ".*/_.*" -E ".*/tests/.*" -E ".*/benchmarks/.*" -E "./CMake.*CompilerId.c" diff --git a/.github/scripts/run-cmake-test b/.github/scripts/run-cmake-test index b3dfe688..90985932 100755 --- a/.github/scripts/run-cmake-test +++ b/.github/scripts/run-cmake-test @@ -26,19 +26,11 @@ cmake "${WORKSPACE}/3rdparty/googletest" -DCMAKE_INSTALL_PREFIX="${THIRDPARTY_PR make -j$(nproc) make install -# Build with external dependencies and test coverage +# Build with external dependencies mkdir "${WORKSPACE}/_build_coverage" && cd $_ -CFLAGS="--coverage" CXXFLAGS="--coverage" LDFLAGS="--coverage" cmake .. -DCMAKE_INSTALL_PREFIX="${THIRDPARTY_PREFIX_DIR}" -DUSE_THIRDPARTY_LIBRARIES=OFF +cmake .. -DCMAKE_INSTALL_PREFIX="${THIRDPARTY_PREFIX_DIR}" -DUSE_THIRDPARTY_LIBRARIES=OFF make -j$(nproc) ctest -V -LE Benchmark mkdir -p deploy make DESTDIR="${PWD}/deploy" install - -# Collect coverage data - -#if [[ "${OS_ARG}" == "ubuntu"* ]] -#then -# pip install --user cpp-coveralls -# coveralls --root .. --build-root . -E ".*/3rdparty/.*" -E ".*/_.*" -E ".*/tests/.*" -E ".*/benchmarks/.*" -#fi diff --git a/.github/scripts/run-prepare b/.github/scripts/run-prepare index 32b4c443..993365dc 100755 --- a/.github/scripts/run-prepare +++ b/.github/scripts/run-prepare @@ -16,7 +16,7 @@ case "${OS_ARG}" in packages+=(bazel) ;; cmake) - packages+=(libcurl4-openssl-dev) + packages+=(libcurl4-openssl-dev python-pip python-wheel) ;; esac diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 00000000..0207e701 --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,21 @@ +name: Coverage +on: [push, pull_request] + +jobs: + build: + name: Coverage ${{ matrix.buildsystem }} on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + buildsystem: [cmake] + os: [ubuntu-18.04] + steps: + - uses: actions/checkout@master + with: + submodules: true + - name: Prepare + run: .github/scripts/run-prepare ${{ matrix.buildsystem }} ${{ matrix.os }} + - name: Test + env: + COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} + run: .github/scripts/run-cmake-coverage diff --git a/.travis.yml b/.travis.yml index d2c814a6..4ebd2f52 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,27 +11,9 @@ env: addons: apt: packages: - - cmake - - curl - doxygen - - g++ - - gcc - - git - - lcov - - libcurl4-openssl-dev - - python-pip script: - - pushd . - - mkdir _build_coverage - - cd _build_coverage - - CFLAGS="--coverage" CXXFLAGS="--coverage" LDFLAGS="--coverage" cmake .. -DUSE_THIRDPARTY_LIBRARIES=ON - - make -j 4 - - ctest -V -LE Benchmark - - pip install --user cpp-coveralls - - coveralls --root .. --build-root . -E ".*/3rdparty/.*" -E ".*/_.*" -E ".*/tests/.*" -E ".*/benchmarks/.*" - - popd - - pushd . - cd doc - doxygen From d8db181c772a051a337074a20824cb58b46eae3c Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Fri, 1 Nov 2019 14:00:57 +0100 Subject: [PATCH 053/206] fix(ci): Also build with Bazel on Windows --- .github/workflows/continuous-integration-workflow.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/continuous-integration-workflow.yml b/.github/workflows/continuous-integration-workflow.yml index ddcf39cf..4692cd47 100644 --- a/.github/workflows/continuous-integration-workflow.yml +++ b/.github/workflows/continuous-integration-workflow.yml @@ -9,9 +9,6 @@ jobs: matrix: buildsystem: [bazel, cmake] os: [macOS-10.14, ubuntu-16.04, windows-2016] - exclude: - - os: windows-2016 - buildsystem: bazel steps: - uses: actions/checkout@master with: From ca0b1e50c43907fe5553d5fd9514cc086850cb83 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Fri, 1 Nov 2019 17:35:03 +0100 Subject: [PATCH 054/206] feat(core): Improve family.cc coverage --- core/tests/family_test.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/tests/family_test.cc b/core/tests/family_test.cc index 455ad627..8f11e5a5 100644 --- a/core/tests/family_test.cc +++ b/core/tests/family_test.cc @@ -46,6 +46,11 @@ TEST(FamilyTest, remove) { EXPECT_EQ(collected[0].metric.size(), 1U); } +TEST(FamilyTest, removeUnknownMetricMustNotCrash) { + Family family{"total_requests", "Counts all requests", {}}; + family.Remove(nullptr); +} + TEST(FamilyTest, Histogram) { Family family{"request_latency", "Latency Histogram", {}}; auto& histogram1 = family.Add({{"name", "histogram1"}}, From f2a296ead8325a0ce9166e4c04e3a2b8f4f1540b Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Fri, 1 Nov 2019 18:43:02 +0100 Subject: [PATCH 055/206] feat(core): Improve text_serializer.cc coverage --- core/src/text_serializer.cc | 2 - core/tests/CMakeLists.txt | 1 + core/tests/text_serializer_test.cc | 103 +++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 core/tests/text_serializer_test.cc diff --git a/core/src/text_serializer.cc b/core/src/text_serializer.cc index fc84c41e..f1494282 100644 --- a/core/src/text_serializer.cc +++ b/core/src/text_serializer.cc @@ -166,8 +166,6 @@ void SerializeFamily(std::ostream& out, const MetricFamily& family) { SerializeHistogram(out, family, metric); } break; - default: - break; } } } // namespace diff --git a/core/tests/CMakeLists.txt b/core/tests/CMakeLists.txt index cd220cb8..53e6a2ed 100644 --- a/core/tests/CMakeLists.txt +++ b/core/tests/CMakeLists.txt @@ -9,6 +9,7 @@ add_executable(prometheus_test registry_test.cc serializer_test.cc summary_test.cc + text_serializer_test.cc utils_test.cc ) diff --git a/core/tests/text_serializer_test.cc b/core/tests/text_serializer_test.cc new file mode 100644 index 00000000..4a603f62 --- /dev/null +++ b/core/tests/text_serializer_test.cc @@ -0,0 +1,103 @@ +#include "prometheus/text_serializer.h" + +#include + +#include +#include + +#include "prometheus/family.h" +#include "prometheus/gauge.h" +#include "prometheus/histogram.h" +#include "prometheus/summary.h" + +namespace prometheus { +namespace { + +class TextSerializerTest : public testing::Test { + public: + std::string Serialize(MetricType type) const { + MetricFamily metricFamily; + metricFamily.name = name; + metricFamily.help = "my metric help text"; + metricFamily.type = type; + metricFamily.metric = std::vector{metric}; + + std::vector families{metricFamily}; + + return textSerializer.Serialize(families); + } + + const std::string name = "my_metric"; + ClientMetric metric; + TextSerializer textSerializer; +}; + +TEST_F(TextSerializerTest, shouldSerializeNotANumber) { + metric.gauge.value = std::nan(""); + EXPECT_THAT(Serialize(MetricType::Gauge), testing::HasSubstr(name + " Nan")); +} + +TEST_F(TextSerializerTest, shouldSerializeNegativeInfinity) { + metric.gauge.value = -std::numeric_limits::infinity(); + EXPECT_THAT(Serialize(MetricType::Gauge), testing::HasSubstr(name + " -Inf")); +} + +TEST_F(TextSerializerTest, shouldSerializePositiveInfinity) { + metric.gauge.value = std::numeric_limits::infinity(); + EXPECT_THAT(Serialize(MetricType::Gauge), testing::HasSubstr(name + " +Inf")); +} + +TEST_F(TextSerializerTest, shouldEscapeBackslash) { + metric.label.resize(1, ClientMetric::Label{"k", "v\\v"}); + EXPECT_THAT(Serialize(MetricType::Gauge), + testing::HasSubstr(name + "{k=\"v\\\\v\"}")); +} + +TEST_F(TextSerializerTest, shouldEscapeNewline) { + metric.label.resize(1, ClientMetric::Label{"k", "v\nv"}); + EXPECT_THAT(Serialize(MetricType::Gauge), + testing::HasSubstr(name + "{k=\"v\\\nv\"}")); +} + +TEST_F(TextSerializerTest, shouldEscapeDoubleQuote) { + metric.label.resize(1, ClientMetric::Label{"k", "v\"v"}); + EXPECT_THAT(Serialize(MetricType::Gauge), + testing::HasSubstr(name + "{k=\"v\\\"v\"}")); +} + +TEST_F(TextSerializerTest, shouldSerializeUntyped) { + metric.untyped.value = 64.0; + + const auto serialized = Serialize(MetricType::Untyped); + EXPECT_THAT(serialized, testing::HasSubstr(name + " 64.000000")); +} + +TEST_F(TextSerializerTest, shouldSerializeHistogram) { + Histogram histogram{{1}}; + histogram.Observe(0); + histogram.Observe(200); + metric = histogram.Collect(); + + const auto serialized = Serialize(MetricType::Histogram); + EXPECT_THAT(serialized, testing::HasSubstr(name + "_count 2")); + EXPECT_THAT(serialized, testing::HasSubstr(name + "_sum 200.00000")); + EXPECT_THAT(serialized, + testing::HasSubstr(name + "_bucket{le=\"1.000000\"} 1")); + EXPECT_THAT(serialized, testing::HasSubstr(name + "_bucket{le=\"+Inf\"} 2")); +} + +TEST_F(TextSerializerTest, shouldSerializeSummary) { + Summary summary{Summary::Quantiles{{0.5, 0.05}}}; + summary.Observe(0); + summary.Observe(200); + metric = summary.Collect(); + + const auto serialized = Serialize(MetricType::Summary); + EXPECT_THAT(serialized, testing::HasSubstr(name + "_count 2")); + EXPECT_THAT(serialized, testing::HasSubstr(name + "_sum 200.00000")); + EXPECT_THAT(serialized, + testing::HasSubstr(name + "{quantile=\"0.500000\"} 0.000000")); +} + +} // namespace +} // namespace prometheus From 2be75c533ff5e93b20763b0855735be9a38cc6af Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 3 Nov 2019 15:58:10 +0100 Subject: [PATCH 056/206] fix(core): Properly serialize newlines in label values --- core/src/text_serializer.cc | 19 ++++++++++++++++--- core/tests/text_serializer_test.cc | 2 +- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/core/src/text_serializer.cc b/core/src/text_serializer.cc index f1494282..4da59ad2 100644 --- a/core/src/text_serializer.cc +++ b/core/src/text_serializer.cc @@ -24,10 +24,23 @@ void WriteValue(std::ostream& out, double value) { void WriteValue(std::ostream& out, const std::string& value) { for (auto c : value) { - if (c == '\\' || c == '"' || c == '\n') { - out << "\\"; + switch (c) { + case '\n': + out << '\\' << 'n'; + break; + + case '\\': + out << '\\' << c; + break; + + case '"': + out << '\\' << c; + break; + + default: + out << c; + break; } - out << c; } } diff --git a/core/tests/text_serializer_test.cc b/core/tests/text_serializer_test.cc index 4a603f62..7af0d967 100644 --- a/core/tests/text_serializer_test.cc +++ b/core/tests/text_serializer_test.cc @@ -56,7 +56,7 @@ TEST_F(TextSerializerTest, shouldEscapeBackslash) { TEST_F(TextSerializerTest, shouldEscapeNewline) { metric.label.resize(1, ClientMetric::Label{"k", "v\nv"}); EXPECT_THAT(Serialize(MetricType::Gauge), - testing::HasSubstr(name + "{k=\"v\\\nv\"}")); + testing::HasSubstr(name + "{k=\"v\\nv\"}")); } TEST_F(TextSerializerTest, shouldEscapeDoubleQuote) { From b551b5417d513c8a52872f05b53f77202779079b Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 3 Nov 2019 16:26:31 +0100 Subject: [PATCH 057/206] fix(coverage): Use Ubuntu 16.04 for coverage --- .github/workflows/coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 0207e701..30378ee4 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: buildsystem: [cmake] - os: [ubuntu-18.04] + os: [ubuntu-16.04] steps: - uses: actions/checkout@master with: From 582dbb02952436cf0fc8a9ec240c29dba58d8d0e Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 3 Nov 2019 16:21:45 +0100 Subject: [PATCH 058/206] feat(core): Improve text_serializer.cc coverage --- core/tests/text_serializer_test.cc | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/core/tests/text_serializer_test.cc b/core/tests/text_serializer_test.cc index 7af0d967..edd0477e 100644 --- a/core/tests/text_serializer_test.cc +++ b/core/tests/text_serializer_test.cc @@ -72,6 +72,24 @@ TEST_F(TextSerializerTest, shouldSerializeUntyped) { EXPECT_THAT(serialized, testing::HasSubstr(name + " 64.000000")); } +TEST_F(TextSerializerTest, shouldSerializeTimestamp) { + metric.counter.value = 64.0; + metric.timestamp_ms = 1234; + + const auto serialized = Serialize(MetricType::Counter); + EXPECT_THAT(serialized, testing::HasSubstr(name + " 64.000000 1234")); +} + +TEST_F(TextSerializerTest, shouldSerializeHistogramWithNoBuckets) { + metric.histogram.sample_count = 2; + metric.histogram.sample_sum = 32.0; + + const auto serialized = Serialize(MetricType::Histogram); + EXPECT_THAT(serialized, testing::HasSubstr(name + "_count 2")); + EXPECT_THAT(serialized, testing::HasSubstr(name + "_sum 32.00000")); + EXPECT_THAT(serialized, testing::HasSubstr(name + "_bucket{le=\"+Inf\"} 2")); +} + TEST_F(TextSerializerTest, shouldSerializeHistogram) { Histogram histogram{{1}}; histogram.Observe(0); From a9cb9e7c4c75f01e67b9a114f3338cca8deb50e6 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 3 Nov 2019 20:50:35 +0100 Subject: [PATCH 059/206] chore(dependencies): Update Google Benchmark and Test to latest release --- 3rdparty/googletest | 2 +- bazel/repositories.bzl | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/3rdparty/googletest b/3rdparty/googletest index 2fe3bd99..703bd9ca 160000 --- a/3rdparty/googletest +++ b/3rdparty/googletest @@ -1 +1 @@ -Subproject commit 2fe3bd994b3189899d93f1d5a881e725e046fdc2 +Subproject commit 703bd9caab50b139428cea1aaff9974ebee5742e diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index 258b73ff..c7211ccf 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -16,10 +16,10 @@ def prometheus_cpp_repositories(): maybe( http_archive, name = "com_google_googletest", - sha256 = "9bf1fe5182a604b4135edc1a425ae356c9ad15e9b23f9f12a02e80184c3a249c", - strip_prefix = "googletest-release-1.8.1", + sha256 = "9dc9157a9a1551ec7a7e43daea9a694a0bb5fb8bec81235d8a1e6ef64c716dcb", + strip_prefix = "googletest-release-1.10.0", urls = [ - "https://github.com/google/googletest/archive/release-1.8.1.tar.gz", + "https://github.com/google/googletest/archive/release-1.10.0.tar.gz", ], ) @@ -38,10 +38,10 @@ def prometheus_cpp_repositories(): maybe( http_archive, name = "com_github_google_benchmark", - sha256 = "f8e525db3c42efc9c7f3bc5176a8fa893a9a9920bbd08cef30fb56a51854d60d", - strip_prefix = "benchmark-1.4.1", + sha256 = "3c6a165b6ecc948967a1ead710d4a181d7b0fbcaa183ef7ea84604994966221a", + strip_prefix = "benchmark-1.5.0", urls = [ - "https://github.com/google/benchmark/archive/v1.4.1.tar.gz", + "https://github.com/google/benchmark/archive/v1.5.0.tar.gz", ], ) From 9ba908d5b39a83200a9fde7a22a3508d1c5f28f9 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 7 Nov 2019 20:34:35 +0100 Subject: [PATCH 060/206] fix(github): Use macos-latest Github updates the macos fleet to catalina and recommends to stay on macos-latest. --- .github/workflows/continuous-integration-workflow.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/continuous-integration-workflow.yml b/.github/workflows/continuous-integration-workflow.yml index 4692cd47..a3cfd874 100644 --- a/.github/workflows/continuous-integration-workflow.yml +++ b/.github/workflows/continuous-integration-workflow.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: buildsystem: [bazel, cmake] - os: [macOS-10.14, ubuntu-16.04, windows-2016] + os: [macOS-latest, ubuntu-16.04, windows-2016] steps: - uses: actions/checkout@master with: From 9bb4e20560e53fe068820bbf7b7abb0c128f72ad Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 19 Dec 2019 22:28:32 +0100 Subject: [PATCH 061/206] Fix submodule checkout --- .github/workflows/continuous-integration-workflow.yml | 10 +++++++--- .github/workflows/coverage.yml | 8 ++++++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/.github/workflows/continuous-integration-workflow.yml b/.github/workflows/continuous-integration-workflow.yml index a3cfd874..3809bf74 100644 --- a/.github/workflows/continuous-integration-workflow.yml +++ b/.github/workflows/continuous-integration-workflow.yml @@ -10,9 +10,13 @@ jobs: buildsystem: [bazel, cmake] os: [macOS-latest, ubuntu-16.04, windows-2016] steps: - - uses: actions/checkout@master - with: - submodules: true + - uses: actions/checkout@v2 + - name: Checkout submodules + shell: bash + run: | + auth_header="$(git config --local --get http.https://github.com/.extraheader)" + git submodule sync --recursive + git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1 - name: Prepare run: .github/scripts/run-prepare ${{ matrix.buildsystem }} ${{ matrix.os }} - name: Test diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 30378ee4..080db579 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -11,8 +11,12 @@ jobs: os: [ubuntu-16.04] steps: - uses: actions/checkout@master - with: - submodules: true + - name: Checkout submodules + shell: bash + run: | + auth_header="$(git config --local --get http.https://github.com/.extraheader)" + git submodule sync --recursive + git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1 - name: Prepare run: .github/scripts/run-prepare ${{ matrix.buildsystem }} ${{ matrix.os }} - name: Test From 36e08faa8776bbbd999ebb2565c92c6db788ab6d Mon Sep 17 00:00:00 2001 From: Jupp Mueller Date: Thu, 19 Dec 2019 14:15:24 -0800 Subject: [PATCH 062/206] Fix coverage Looks like according to https://github.com/nickmerwin/node-coveralls#github-actions-ci we are missing a branch env variable for github actions coverage support. --- .github/workflows/coverage.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 080db579..094218e4 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -22,4 +22,5 @@ jobs: - name: Test env: COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} + COVERALLS_GIT_BRANCH: "${{ github.ref }}" run: .github/scripts/run-cmake-coverage From 7b63978099979f5728212f0b67a5d3d2c03bdef2 Mon Sep 17 00:00:00 2001 From: Benjamin Worpitz Date: Fri, 20 Dec 2019 06:37:34 +0100 Subject: [PATCH 063/206] Make Collect methods const (#323) * Make Collect methods const Collect methods should not influence the state of the objects in any externally visible way. * Update ABI version * Fix interior mutablility problems Co-authored-by: Jupp Mueller --- CMakeLists.txt | 2 +- core/include/prometheus/collectable.h | 2 +- core/include/prometheus/detail/time_window_quantiles.h | 10 +++++----- core/include/prometheus/family.h | 6 +++--- core/include/prometheus/registry.h | 4 ++-- core/include/prometheus/summary.h | 4 ++-- core/src/detail/time_window_quantiles.cc | 4 ++-- core/src/family.cc | 4 ++-- core/src/registry.cc | 2 +- core/src/summary.cc | 2 +- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 28e193f6..b1d855a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.5 FATAL_ERROR) -project(prometheus-cpp VERSION 0.8.0) +project(prometheus-cpp VERSION 0.9.0) include(GenerateExportHeader) include(GNUInstallDirs) diff --git a/core/include/prometheus/collectable.h b/core/include/prometheus/collectable.h index aaf1dce9..e268e508 100644 --- a/core/include/prometheus/collectable.h +++ b/core/include/prometheus/collectable.h @@ -19,7 +19,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Collectable { virtual ~Collectable() = default; /// \brief Returns a list of metrics and their samples. - virtual std::vector Collect() = 0; + virtual std::vector Collect() const = 0; }; } // namespace prometheus diff --git a/core/include/prometheus/detail/time_window_quantiles.h b/core/include/prometheus/detail/time_window_quantiles.h index d2a90c31..3a3ac65c 100644 --- a/core/include/prometheus/detail/time_window_quantiles.h +++ b/core/include/prometheus/detail/time_window_quantiles.h @@ -17,17 +17,17 @@ class PROMETHEUS_CPP_CORE_EXPORT TimeWindowQuantiles { TimeWindowQuantiles(const std::vector& quantiles, Clock::duration max_age_seconds, int age_buckets); - double get(double q); + double get(double q) const; void insert(double value); private: - CKMSQuantiles& rotate(); + CKMSQuantiles& rotate() const; const std::vector& quantiles_; - std::vector ckms_quantiles_; - std::size_t current_bucket_; + mutable std::vector ckms_quantiles_; + mutable std::size_t current_bucket_; - Clock::time_point last_rotation_; + mutable Clock::time_point last_rotation_; const Clock::duration rotation_interval_; }; diff --git a/core/include/prometheus/family.h b/core/include/prometheus/family.h index b047f3ea..aa946832 100644 --- a/core/include/prometheus/family.h +++ b/core/include/prometheus/family.h @@ -133,7 +133,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Family : public Collectable { /// Collect is called by the Registry when collecting metrics. /// /// \return Zero or more samples for each dimensional data. - std::vector Collect() override; + std::vector Collect() const override; private: std::unordered_map> metrics_; @@ -143,9 +143,9 @@ class PROMETHEUS_CPP_CORE_EXPORT Family : public Collectable { const std::string name_; const std::string help_; const std::map constant_labels_; - std::mutex mutex_; + mutable std::mutex mutex_; - ClientMetric CollectMetric(std::size_t hash, T* metric); + ClientMetric CollectMetric(std::size_t hash, T* metric) const; T& Add(const std::map& labels, std::unique_ptr object); }; diff --git a/core/include/prometheus/registry.h b/core/include/prometheus/registry.h index bef7d924..c8fdeb20 100644 --- a/core/include/prometheus/registry.h +++ b/core/include/prometheus/registry.h @@ -71,7 +71,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Registry : public Collectable { /// function. /// /// \return Zero or more metrics and their samples. - std::vector Collect() override; + std::vector Collect() const override; private: template @@ -92,7 +92,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Registry : public Collectable { std::vector>> gauges_; std::vector>> histograms_; std::vector>> summaries_; - std::mutex mutex_; + mutable std::mutex mutex_; }; } // namespace prometheus diff --git a/core/include/prometheus/summary.h b/core/include/prometheus/summary.h index 5cec9673..7f6a4556 100644 --- a/core/include/prometheus/summary.h +++ b/core/include/prometheus/summary.h @@ -81,11 +81,11 @@ class PROMETHEUS_CPP_CORE_EXPORT Summary { /// \brief Get the current value of the summary. /// /// Collect is called by the Registry when collecting metrics. - ClientMetric Collect(); + ClientMetric Collect() const; private: const Quantiles quantiles_; - std::mutex mutex_; + mutable std::mutex mutex_; std::uint64_t count_; double sum_; detail::TimeWindowQuantiles quantile_values_; diff --git a/core/src/detail/time_window_quantiles.cc b/core/src/detail/time_window_quantiles.cc index eec6f2d3..e767122d 100644 --- a/core/src/detail/time_window_quantiles.cc +++ b/core/src/detail/time_window_quantiles.cc @@ -12,7 +12,7 @@ TimeWindowQuantiles::TimeWindowQuantiles( last_rotation_(Clock::now()), rotation_interval_(max_age / age_buckets) {} -double TimeWindowQuantiles::get(double q) { +double TimeWindowQuantiles::get(double q) const { CKMSQuantiles& current_bucket = rotate(); return current_bucket.get(q); } @@ -24,7 +24,7 @@ void TimeWindowQuantiles::insert(double value) { } } -CKMSQuantiles& TimeWindowQuantiles::rotate() { +CKMSQuantiles& TimeWindowQuantiles::rotate() const { auto delta = Clock::now() - last_rotation_; while (delta > rotation_interval_) { ckms_quantiles_[current_bucket_].reset(); diff --git a/core/src/family.cc b/core/src/family.cc index a9a9af9b..83631abc 100644 --- a/core/src/family.cc +++ b/core/src/family.cc @@ -69,7 +69,7 @@ const std::map Family::GetConstantLabels() const { } template -std::vector Family::Collect() { +std::vector Family::Collect() const { std::lock_guard lock{mutex_}; auto family = MetricFamily{}; family.name = name_; @@ -82,7 +82,7 @@ std::vector Family::Collect() { } template -ClientMetric Family::CollectMetric(std::size_t hash, T* metric) { +ClientMetric Family::CollectMetric(std::size_t hash, T* metric) const { auto collected = metric->Collect(); auto add_label = [&collected](const std::pair& label_pair) { diff --git a/core/src/registry.cc b/core/src/registry.cc index 59084ed1..1a30a233 100644 --- a/core/src/registry.cc +++ b/core/src/registry.cc @@ -38,7 +38,7 @@ Registry::Registry(InsertBehavior insert_behavior) Registry::~Registry() = default; -std::vector Registry::Collect() { +std::vector Registry::Collect() const { std::lock_guard lock{mutex_}; auto results = std::vector{}; diff --git a/core/src/summary.cc b/core/src/summary.cc index 2d913aa2..7ed9de61 100644 --- a/core/src/summary.cc +++ b/core/src/summary.cc @@ -17,7 +17,7 @@ void Summary::Observe(const double value) { quantile_values_.insert(value); } -ClientMetric Summary::Collect() { +ClientMetric Summary::Collect() const { auto metric = ClientMetric{}; std::lock_guard lock(mutex_); From 3ec526a3b401b089bb8bf672b74e9fda9aa9b528 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 26 Dec 2019 17:01:03 +0100 Subject: [PATCH 064/206] Update Bazel build instructions (#326) --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index be8e6836..483ecebf 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ http_archive( urls = ["https://github.com/jupp0r/prometheus-cpp/archive/master.zip"], ) -load("@com_github_jupp0r_prometheus_cpp//:repositories.bzl", "prometheus_cpp_repositories") +load("@com_github_jupp0r_prometheus_cpp//bazel:repositories.bzl", "prometheus_cpp_repositories") prometheus_cpp_repositories() ``` @@ -133,15 +133,15 @@ cc_binary( ``` When you call `prometheus_cpp_repositories()` in your `WORKSPACE` file, -you introduce the following dependencies, if they do not exist yet, to your project: +you load the following dependencies, if they do not exist yet, into your project: -* `load_civetweb()` to load `civetweb` rules for Civetweb -* `load_com_google_googletest()` to load `com_google_googletest` rules for Google gtest -* `load_com_google_googlebenchmark()` to load `com_github_google_benchmark` rules for Googlebenchmark -* `load_com_github_curl()` to load `com_github_curl` rules for curl -* `load_net_zlib_zlib()` to load `net_zlib_zlib` rules for zlib +* `civetweb` for [Civetweb](https://github.com/civetweb/civetweb) +* `com_google_googletest` for [Google Test](https://github.com/google/googletest) +* `com_github_google_benchmark` for [Google Benchmark](https://github.com/google/benchmark) +* `com_github_curl` for [curl](https://curl.haxx.se/) +* `net_zlib_zlib` for [zlib](http://www.zlib.net/) -The list of dependencies is also available from file `repositories.bzl`. +The list of dependencies is also available from file [repositories.bzl](bazel/repositories.bzl). ## Contributing From 7a4b529869daad005a3f58b5858423bdbcdcbe9f Mon Sep 17 00:00:00 2001 From: David Avedissian Date: Thu, 30 Jan 2020 22:35:43 +0000 Subject: [PATCH 065/206] Avoid copying the histogram metric buckets. (#331) --- core/include/prometheus/histogram.h | 2 +- core/src/histogram.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/include/prometheus/histogram.h b/core/include/prometheus/histogram.h index a9527870..c727f3d6 100644 --- a/core/include/prometheus/histogram.h +++ b/core/include/prometheus/histogram.h @@ -57,7 +57,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Histogram { /// Increments counters given a count for each bucket. (i.e. the caller of /// this function must have already sorted the values into buckets). /// Also increments the total sum of all observations by the given value. - void ObserveMultiple(const std::vector bucket_increments, + void ObserveMultiple(const std::vector& bucket_increments, const double sum_of_values); /// \brief Get the current value of the counter. diff --git a/core/src/histogram.cc b/core/src/histogram.cc index a1c4df00..4a40d535 100644 --- a/core/src/histogram.cc +++ b/core/src/histogram.cc @@ -24,7 +24,7 @@ void Histogram::Observe(const double value) { bucket_counts_[bucket_index].Increment(); } -void Histogram::ObserveMultiple(const std::vector bucket_increments, +void Histogram::ObserveMultiple(const std::vector& bucket_increments, const double sum_of_values) { if (bucket_increments.size() != bucket_counts_.size()) { throw std::length_error( From 023c93e4e504d0954b01cdde13bd293865880388 Mon Sep 17 00:00:00 2001 From: Cheney Wang <38240633+Cheney-W@users.noreply.github.com> Date: Tue, 11 Feb 2020 10:07:45 -0800 Subject: [PATCH 066/206] Include missing --- core/src/histogram.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/histogram.cc b/core/src/histogram.cc index 4a40d535..80235298 100644 --- a/core/src/histogram.cc +++ b/core/src/histogram.cc @@ -4,6 +4,7 @@ #include #include #include +#include namespace prometheus { From 6825470cfc6c8f9d825100718041aab4f2c8f9ee Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Wed, 12 Feb 2020 20:25:53 +0100 Subject: [PATCH 067/206] chore: Use libcurl 7.68.0 --- bazel/repositories.bzl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index c7211ccf..a7d85dae 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -26,11 +26,11 @@ def prometheus_cpp_repositories(): maybe( http_archive, name = "com_github_curl", - sha256 = "d0393da38ac74ffac67313072d7fe75b1fa1010eb5987f63f349b024a36b7ffb", - strip_prefix = "curl-7.66.0", + sha256 = "1dd7604e418b0b9a9077f62f763f6684c1b092a7bc17e3f354b8ad5c964d7358", + strip_prefix = "curl-7.68.0", urls = [ - "https://github.com/curl/curl/releases/download/curl-7_66_0/curl-7.66.0.tar.gz", - "https://curl.haxx.se/download/curl-7.66.0.tar.gz", + "https://github.com/curl/curl/releases/download/curl-7_68_0/curl-7.68.0.tar.gz", + "https://curl.haxx.se/download/curl-7.68.0.tar.gz", ], build_file = "@com_github_jupp0r_prometheus_cpp//bazel:curl.BUILD", ) From 3018a51030a9d8ee6ac6d64c092cfe2372113982 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Wed, 12 Feb 2020 20:59:25 +0100 Subject: [PATCH 068/206] feat(pull): Add getter for listening ports Closes: #334 --- core/tests/CMakeLists.txt | 8 ++++---- pull/include/prometheus/exposer.h | 2 ++ pull/src/exposer.cc | 5 +++++ pull/tests/CMakeLists.txt | 1 + pull/tests/unit/BUILD.bazel | 13 +++++++++++++ pull/tests/unit/CMakeLists.txt | 15 +++++++++++++++ pull/tests/unit/exposer_test.cc | 25 +++++++++++++++++++++++++ 7 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 pull/tests/unit/BUILD.bazel create mode 100644 pull/tests/unit/CMakeLists.txt create mode 100644 pull/tests/unit/exposer_test.cc diff --git a/core/tests/CMakeLists.txt b/core/tests/CMakeLists.txt index 53e6a2ed..d641a852 100644 --- a/core/tests/CMakeLists.txt +++ b/core/tests/CMakeLists.txt @@ -1,5 +1,5 @@ -add_executable(prometheus_test +add_executable(prometheus_core_test builder_test.cc check_names_test.cc counter_test.cc @@ -13,13 +13,13 @@ add_executable(prometheus_test utils_test.cc ) -target_link_libraries(prometheus_test +target_link_libraries(prometheus_core_test PRIVATE ${PROJECT_NAME}::core GTest::gmock_main ) add_test( - NAME prometheus_test - COMMAND prometheus_test + NAME prometheus_core_test + COMMAND prometheus_core_test ) diff --git a/pull/include/prometheus/exposer.h b/pull/include/prometheus/exposer.h index c730360c..0917ba98 100644 --- a/pull/include/prometheus/exposer.h +++ b/pull/include/prometheus/exposer.h @@ -26,6 +26,8 @@ class PROMETHEUS_CPP_PULL_EXPORT Exposer { ~Exposer(); void RegisterCollectable(const std::weak_ptr& collectable); + std::vector GetListeningPorts() const; + private: std::unique_ptr server_; std::vector> collectables_; diff --git a/pull/src/exposer.cc b/pull/src/exposer.cc index 966d04ae..ad22b7e0 100644 --- a/pull/src/exposer.cc +++ b/pull/src/exposer.cc @@ -30,4 +30,9 @@ void Exposer::RegisterCollectable( const std::weak_ptr& collectable) { collectables_.push_back(collectable); } + +std::vector Exposer::GetListeningPorts() const { + return server_->getListeningPorts(); +} + } // namespace prometheus diff --git a/pull/tests/CMakeLists.txt b/pull/tests/CMakeLists.txt index 26e40e61..729c6ee0 100644 --- a/pull/tests/CMakeLists.txt +++ b/pull/tests/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(integration) +add_subdirectory(unit) diff --git a/pull/tests/unit/BUILD.bazel b/pull/tests/unit/BUILD.bazel new file mode 100644 index 00000000..fc174146 --- /dev/null +++ b/pull/tests/unit/BUILD.bazel @@ -0,0 +1,13 @@ +cc_test( + name = "unit", + srcs = glob([ + "*.cc", + "*.h", + ]), + copts = ["-Iexternal/googletest/include"], + linkstatic = True, + deps = [ + "//pull", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/pull/tests/unit/CMakeLists.txt b/pull/tests/unit/CMakeLists.txt new file mode 100644 index 00000000..5c5c4857 --- /dev/null +++ b/pull/tests/unit/CMakeLists.txt @@ -0,0 +1,15 @@ + +add_executable(prometheus_pull_test + exposer_test.cc +) + +target_link_libraries(prometheus_pull_test + PRIVATE + ${PROJECT_NAME}::pull + GTest::gmock_main +) + +add_test( + NAME prometheus_pull_test + COMMAND prometheus_pull_test +) diff --git a/pull/tests/unit/exposer_test.cc b/pull/tests/unit/exposer_test.cc new file mode 100644 index 00000000..0c46f95b --- /dev/null +++ b/pull/tests/unit/exposer_test.cc @@ -0,0 +1,25 @@ +#include "prometheus/exposer.h" + +#include + +namespace prometheus { +namespace { + +using namespace testing; + +TEST(ExposerTest, listenOnDistinctPorts) { + Exposer firstExposer{"0.0.0.0:0"}; + auto firstExposerPorts = firstExposer.GetListeningPorts(); + ASSERT_EQ(1u, firstExposerPorts.size()); + EXPECT_NE(0, firstExposerPorts.front()); + + Exposer secondExposer{"0.0.0.0:0"}; + auto secondExposerPorts = secondExposer.GetListeningPorts(); + ASSERT_EQ(1u, secondExposerPorts.size()); + EXPECT_NE(0, secondExposerPorts.front()); + + EXPECT_NE(firstExposerPorts, secondExposerPorts); +} + +} // namespace +} // namespace prometheus From 8697b34053e71b6d396323232ac7f80924068e14 Mon Sep 17 00:00:00 2001 From: Stephen Bates Date: Fri, 28 Feb 2020 16:28:22 -0700 Subject: [PATCH 069/206] CMake: Add support for Debian and RPM package generation Add a Cpack related section to CMakeLists.txt to create a package and a package_source target for Debian (.deb) and RPM (.rpm) package generation. Update the README.md to provide information on how to generate these packages. Since I am not a maintainer of prometheus-cpp I leave contact section of the CPACK definitions undefined (CPACK_PACKAGE_CONTACT). Addresses [1]: [1]: https://github.com/jupp0r/prometheus-cpp/issues/339 --- CMakeLists.txt | 12 ++++++++++++ README.md | 22 ++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index b1d855a5..56d26e6e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,3 +104,15 @@ add_feature_info("Pull" "${ENABLE_PULL}" "support for pulling metrics") add_feature_info("Push" "${ENABLE_PUSH}" "support for pushing metrics to a push-gateway") add_feature_info("Compression" "${ENABLE_COMPRESSION}" "support for zlib compression of metrics") feature_summary(WHAT ALL) + +# packaging + +set(CPACK_GENERATOR "DEB;RPM") +set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) +set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) +set(CPACK_RPM_PACKAGE_AUTOREQPROV ON) +set(CPACK_RPM_FILE_NAME RPM-DEFAULT) +set(CPACK_PACKAGE_DESCRIPTION "C++ library for Prometheus exporters") +set(CPACK_PACKAGE_RELOCATABLE OFF) + +INCLUDE(CPack) diff --git a/README.md b/README.md index 483ecebf..30d72005 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,28 @@ you load the following dependencies, if they do not exist yet, into your project The list of dependencies is also available from file [repositories.bzl](bazel/repositories.bzl). +## Packaging + +You can generate a Debian package (.deb) and RPM (.rpm) for the static +or dynamic libraries so they can be easily installed on other systems +using CMake. + +``` shell +# fetch third-party dependencies +git submodule init +git submodule update + +mkdir _build +cd _build + +# run cmake +cmake .. -DBUILD_SHARED_LIBS=ON # or OFF for static libraries + +# build +make -j 4 package +``` +This will generate an appropriately named .deb and .rpm in the +```_build``` folder. ## Contributing From a80e534870a8be98c356e3e9e7dc0dce2490407a Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 29 Feb 2020 14:52:29 +0100 Subject: [PATCH 070/206] Add cpack configuration and readme Fix: #339 --- CMakeLists.txt | 30 ++++++++++++++++++------------ README.md | 31 ++++++++++++++++++------------- 2 files changed, 36 insertions(+), 25 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 56d26e6e..a1bd8389 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,6 +97,24 @@ install( DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" ) +# packaging + +if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) + set(CPACK_PACKAGE_CONTACT "prometheus-cpp@@noreply.github.com") + set(CPACK_PACKAGE_DESCRIPTION "C++ library for Prometheus exporters") + set(CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/jupp0r/prometheus-cpp") + set(CPACK_PACKAGE_RELOCATABLE OFF) + set(CPACK_PACKAGE_VENDOR "The prometheus-cpp authors") + + set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) + set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) + + set(CPACK_RPM_PACKAGE_AUTOREQPROV ON) + set(CPACK_RPM_FILE_NAME RPM-DEFAULT) + + include(CPack) +endif() + # summary include(FeatureSummary) @@ -104,15 +122,3 @@ add_feature_info("Pull" "${ENABLE_PULL}" "support for pulling metrics") add_feature_info("Push" "${ENABLE_PUSH}" "support for pushing metrics to a push-gateway") add_feature_info("Compression" "${ENABLE_COMPRESSION}" "support for zlib compression of metrics") feature_summary(WHAT ALL) - -# packaging - -set(CPACK_GENERATOR "DEB;RPM") -set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) -set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) -set(CPACK_RPM_PACKAGE_AUTOREQPROV ON) -set(CPACK_RPM_FILE_NAME RPM-DEFAULT) -set(CPACK_PACKAGE_DESCRIPTION "C++ library for Prometheus exporters") -set(CPACK_PACKAGE_RELOCATABLE OFF) - -INCLUDE(CPack) diff --git a/README.md b/README.md index 30d72005..55cbb7e1 100644 --- a/README.md +++ b/README.md @@ -145,26 +145,31 @@ The list of dependencies is also available from file [repositories.bzl](bazel/re ## Packaging -You can generate a Debian package (.deb) and RPM (.rpm) for the static -or dynamic libraries so they can be easily installed on other systems -using CMake. +By configuring CPack you can generate an installer like a +Debian package (.deb) or RPM (.rpm) for the static or dynamic +libraries so they can be easily installed on +other systems. + +Please refer to the [CPack](https://cmake.org/cmake/help/latest/module/CPack.html) +documentation for all available generators and their +configuration options. + +To generate a Debian package you could follow these steps: ``` shell # fetch third-party dependencies -git submodule init -git submodule update - -mkdir _build -cd _build +git submodule update --init # run cmake -cmake .. -DBUILD_SHARED_LIBS=ON # or OFF for static libraries +cmake -B_build -DCPACK_GENERATOR=DEB -DBUILD_SHARED_LIBS=ON # or OFF for static libraries -# build -make -j 4 package +# build and package +cmake --build _build --target package --parallel $(nproc) ``` -This will generate an appropriately named .deb and .rpm in the -```_build``` folder. + +This will place an appropriately named .deb in the +`_build` folder. To build a RPM package set the `CPACK_GENERATOR` +variable to `RPM`. ## Contributing From 62d673f09cb1a321c1516c6a7e3b944183007913 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 29 Feb 2020 15:56:57 +0100 Subject: [PATCH 071/206] feat(core): Expect working German locale --- core/tests/serializer_test.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/tests/serializer_test.cc b/core/tests/serializer_test.cc index f935a3b0..a13b3ade 100644 --- a/core/tests/serializer_test.cc +++ b/core/tests/serializer_test.cc @@ -24,10 +24,14 @@ class SerializerTest : public testing::Test { }; #ifndef _WIN32 +// This test expects a working German locale to test that floating +// point numbers do not use , but . as a delimiter. +// +// On Debian systems they can be generated by "locale-gen de_DE.UTF-8" TEST_F(SerializerTest, shouldSerializeLocaleIndependent) { // save and change locale const std::locale oldLocale = std::locale::classic(); - std::locale::global(std::locale("de_DE.UTF-8")); + ASSERT_NO_THROW(std::locale::global(std::locale("de_DE.UTF-8"))); const auto serialized = textSerializer.Serialize(collected); EXPECT_THAT(serialized, testing::HasSubstr("1.0")); From 9463d7b04f3ccb8b8d8cce3f81a109ddf26f5488 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 1 Mar 2020 14:47:55 +0100 Subject: [PATCH 072/206] fix(cmake): Explicitly initialize package version for older cmake Closes: #342 --- CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index a1bd8389..73f942cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,6 +106,12 @@ if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) set(CPACK_PACKAGE_RELOCATABLE OFF) set(CPACK_PACKAGE_VENDOR "The prometheus-cpp authors") + if(CMAKE_VERSION VERSION_LESS "3.12") + set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}") + set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}") + set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}") + endif() + set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) From 5c771de785134bf6bf507fa0bed6f6eabd020128 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Fri, 13 Mar 2020 13:16:56 +0100 Subject: [PATCH 073/206] core: Skip serialization test if locale is not available Closes: #345 --- core/tests/raii_locale.h | 15 +++++++++++++++ core/tests/serializer_test.cc | 21 ++++++++++++++------- 2 files changed, 29 insertions(+), 7 deletions(-) create mode 100644 core/tests/raii_locale.h diff --git a/core/tests/raii_locale.h b/core/tests/raii_locale.h new file mode 100644 index 00000000..592d74f2 --- /dev/null +++ b/core/tests/raii_locale.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +class RAIILocale { + public: + RAIILocale(const char* name) : savedLocale_(std::locale::classic()) { + std::locale::global(std::locale(name)); + } + + ~RAIILocale() { std::locale::global(savedLocale_); } + + private: + const std::locale savedLocale_; +}; diff --git a/core/tests/serializer_test.cc b/core/tests/serializer_test.cc index a13b3ade..90550ee9 100644 --- a/core/tests/serializer_test.cc +++ b/core/tests/serializer_test.cc @@ -1,9 +1,13 @@ #include "prometheus/counter.h" +#include "prometheus/detail/future_std.h" #include "prometheus/family.h" #include "prometheus/text_serializer.h" +#include "raii_locale.h" + #include -#include + +#include #include namespace prometheus { @@ -29,15 +33,18 @@ class SerializerTest : public testing::Test { // // On Debian systems they can be generated by "locale-gen de_DE.UTF-8" TEST_F(SerializerTest, shouldSerializeLocaleIndependent) { - // save and change locale - const std::locale oldLocale = std::locale::classic(); - ASSERT_NO_THROW(std::locale::global(std::locale("de_DE.UTF-8"))); + std::unique_ptr localeWithCommaDecimalSeparator; + + // ignore missing locale and skip test if setup fails + try { + localeWithCommaDecimalSeparator = + detail::make_unique("de_DE.UTF-8"); + } catch (std::runtime_error&) { + GTEST_SKIP(); + } const auto serialized = textSerializer.Serialize(collected); EXPECT_THAT(serialized, testing::HasSubstr("1.0")); - - // restore locale - std::locale::global(oldLocale); } #endif From d217a88eda183ab7d66a46c59373b5033471922a Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 15 Mar 2020 12:01:40 +0100 Subject: [PATCH 074/206] chore(push): Update curl to 7.69.1 --- bazel/repositories.bzl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index a7d85dae..e2d0e0ba 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -26,11 +26,11 @@ def prometheus_cpp_repositories(): maybe( http_archive, name = "com_github_curl", - sha256 = "1dd7604e418b0b9a9077f62f763f6684c1b092a7bc17e3f354b8ad5c964d7358", - strip_prefix = "curl-7.68.0", + sha256 = "01ae0c123dee45b01bbaef94c0bc00ed2aec89cb2ee0fd598e0d302a6b5e0a98", + strip_prefix = "curl-7.69.1", urls = [ - "https://github.com/curl/curl/releases/download/curl-7_68_0/curl-7.68.0.tar.gz", - "https://curl.haxx.se/download/curl-7.68.0.tar.gz", + "https://github.com/curl/curl/releases/download/curl-7_69_1/curl-7.69.1.tar.gz", + "https://curl.haxx.se/download/curl-7.69.1.tar.gz", ], build_file = "@com_github_jupp0r_prometheus_cpp//bazel:curl.BUILD", ) From 09d36a5037278ce392fe88b3809e237b238e2901 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Mon, 16 Mar 2020 17:00:36 +0100 Subject: [PATCH 075/206] ci: use vcpkg for external dependencies --- .github/scripts/run-cmake-coverage | 2 +- .github/scripts/run-cmake-test | 19 ++-------- .github/scripts/run-cmake-test.cmd | 10 ++++++ .github/scripts/run-prepare | 12 +++++-- .github/scripts/run-prepare.cmd | 5 +++ 3rdparty/build_for_travis.sh | 18 ---------- cmake/Findcivetweb.cmake | 56 ------------------------------ pull/CMakeLists.txt | 4 +-- 8 files changed, 31 insertions(+), 95 deletions(-) delete mode 100755 3rdparty/build_for_travis.sh delete mode 100644 cmake/Findcivetweb.cmake diff --git a/.github/scripts/run-cmake-coverage b/.github/scripts/run-cmake-coverage index 492216df..1dc61ef4 100755 --- a/.github/scripts/run-cmake-coverage +++ b/.github/scripts/run-cmake-coverage @@ -10,7 +10,7 @@ pip install --user cpp-coveralls # Build with coverage mkdir "${WORKSPACE}/_build_coverage" && cd $_ -CFLAGS="--coverage" CXXFLAGS="--coverage" LDFLAGS="--coverage" cmake .. +CFLAGS="--coverage" CXXFLAGS="--coverage" LDFLAGS="--coverage" cmake .. -DUSE_THIRDPARTY_LIBRARIES=OFF "-DCMAKE_TOOLCHAIN_FILE=${VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake" make -j$(nproc) ctest -V -LE Benchmark diff --git a/.github/scripts/run-cmake-test b/.github/scripts/run-cmake-test index 90985932..49a94a52 100755 --- a/.github/scripts/run-cmake-test +++ b/.github/scripts/run-cmake-test @@ -3,33 +3,20 @@ set -euo pipefail WORKSPACE=$(cd "$(dirname "${BASH_SOURCE[0]}")"/../.. && /bin/pwd -P) -THIRDPARTY_PREFIX_DIR="${WORKSPACE}/_opt" # Build with internal dependencies mkdir "${WORKSPACE}/_build_internal_deps" && cd $_ -cmake .. -DUSE_THIRDPARTY_LIBRARIES=ON -DENABLE_WARNINGS_AS_ERRORS=ON +cmake .. -DUSE_THIRDPARTY_LIBRARIES=ON -DENABLE_WARNINGS_AS_ERRORS=ON -DENABLE_COMPRESSION=OFF -DENABLE_PUSH=OFF make -j$(nproc) ctest -V mkdir -p deploy make DESTDIR="${PWD}/deploy" install -# Build dependencies - -mkdir "${WORKSPACE}/_build_civetweb" && cd $_ -cmake "${WORKSPACE}/3rdparty/civetweb" -DCMAKE_INSTALL_PREFIX="${THIRDPARTY_PREFIX_DIR}" -DCIVETWEB_ENABLE_CXX=ON -DCIVETWEB_ENABLE_SSL=OFF -DCIVETWEB_BUILD_TESTING=OFF -make -j$(nproc) -make install - -mkdir "${WORKSPACE}/_build_googletest" && cd $_ -cmake "${WORKSPACE}/3rdparty/googletest" -DCMAKE_INSTALL_PREFIX="${THIRDPARTY_PREFIX_DIR}" -make -j$(nproc) -make install - # Build with external dependencies -mkdir "${WORKSPACE}/_build_coverage" && cd $_ -cmake .. -DCMAKE_INSTALL_PREFIX="${THIRDPARTY_PREFIX_DIR}" -DUSE_THIRDPARTY_LIBRARIES=OFF +mkdir "${WORKSPACE}/_build" && cd $_ +cmake .. -DUSE_THIRDPARTY_LIBRARIES=OFF "-DCMAKE_TOOLCHAIN_FILE=${VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake" make -j$(nproc) ctest -V -LE Benchmark mkdir -p deploy diff --git a/.github/scripts/run-cmake-test.cmd b/.github/scripts/run-cmake-test.cmd index eebb4525..86b8a67f 100644 --- a/.github/scripts/run-cmake-test.cmd +++ b/.github/scripts/run-cmake-test.cmd @@ -5,3 +5,13 @@ cmake --build . --config Debug || EXIT /B 1 cmake --build . --config Release || EXIT /B 1 ctest -C Debug -V -LE Benchmark || EXIT /B 1 ctest -C Release -V || EXIT /B 1 +cd .. || EXIT /B 1 + +mkdir "_build" || EXIT /B 1 +cd "_build" || EXIT /B 1 +cmake .. -DUSE_THIRDPARTY_LIBRARIES=OFF -DCMAKE_TOOLCHAIN_FILE=%VCPKG_INSTALLATION_ROOT%\scripts\buildsystems\vcpkg.cmake || EXIT /B 1 +cmake --build . --config Debug || EXIT /B 1 +cmake --build . --config Release || EXIT /B 1 +ctest -C Debug -V -LE Benchmark || EXIT /B 1 +ctest -C Release -V || EXIT /B 1 +cd .. || EXIT /B 1 diff --git a/.github/scripts/run-prepare b/.github/scripts/run-prepare index 993365dc..4f266273 100755 --- a/.github/scripts/run-prepare +++ b/.github/scripts/run-prepare @@ -16,7 +16,7 @@ case "${OS_ARG}" in packages+=(bazel) ;; cmake) - packages+=(libcurl4-openssl-dev python-pip python-wheel) + packages+=(python-pip python-wheel) ;; esac @@ -32,7 +32,7 @@ case "${OS_ARG}" in ;; macOS*) - packages=(google-benchmark prometheus telegraf) + packages=(prometheus telegraf) case "${BUILDSYSTEM_ARG}" in bazel) @@ -45,3 +45,11 @@ case "${OS_ARG}" in brew install "${packages[@]}" ;; esac + +case "${BUILDSYSTEM_ARG}" in + bazel) + ;; + cmake) + "${VCPKG_INSTALLATION_ROOT}/vcpkg" install benchmark civetweb curl gtest zlib + ;; +esac diff --git a/.github/scripts/run-prepare.cmd b/.github/scripts/run-prepare.cmd index c6789a10..f4d2b1ef 100644 --- a/.github/scripts/run-prepare.cmd +++ b/.github/scripts/run-prepare.cmd @@ -1,3 +1,8 @@ if [%1] == [bazel] ( choco install bazel -y || EXIT /B 1 ) + +if [%1] == [cmake] ( + %VCPKG_INSTALLATION_ROOT%/vcpkg install benchmark civetweb curl gtest zlib || EXIT /B 1 +) + diff --git a/3rdparty/build_for_travis.sh b/3rdparty/build_for_travis.sh deleted file mode 100755 index da895bb7..00000000 --- a/3rdparty/build_for_travis.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -THIRDPARTY_ROOT=$(cd $(dirname "${BASH_SOURCE[0]}") && /bin/pwd -P) -INSTALL_PREFIX="${TRAVIS_BUILD_DIR:?}/_opt" - -mkdir "${THIRDPARTY_ROOT}/civetweb/_build" -cd "${THIRDPARTY_ROOT}/civetweb/_build" -cmake .. -DCMAKE_INSTALL_PREFIX="${INSTALL_PREFIX}" -DCIVETWEB_ENABLE_CXX=ON -DCIVETWEB_ENABLE_SSL=OFF -DCIVETWEB_BUILD_TESTING=OFF -make -j4 -make install - -mkdir "${THIRDPARTY_ROOT}/googletest/_build" -cd "${THIRDPARTY_ROOT}/googletest/_build" -cmake .. -DCMAKE_INSTALL_PREFIX="${INSTALL_PREFIX}" -make -j4 -make install diff --git a/cmake/Findcivetweb.cmake b/cmake/Findcivetweb.cmake deleted file mode 100644 index 8a170269..00000000 --- a/cmake/Findcivetweb.cmake +++ /dev/null @@ -1,56 +0,0 @@ -find_path(CIVETWEB_INCLUDE_DIR - NAMES civetweb.h - DOC "The CivetWeb include directory" -) - -find_path(CIVETWEB_CXX_INCLUDE_DIR - NAMES CivetServer.h - DOC "The CivetWeb C++ include directory" -) - -find_library(CIVETWEB_LIBRARY - NAMES civetweb - DOC "The CivetWeb library" -) - -find_library(CIVETWEB_CXX_LIBRARY - NAMES civetweb-cpp - DOC "The CivetWeb C++ library" -) - -mark_as_advanced(CIVETWEB_LIBRARY CIVETWEB_CXX_LIBRARY CIVETWEB_INCLUDE_DIR CIVETWEB_CXX_INCLUDE_DIR) - -if(CIVETWEB_INCLUDE_DIR AND EXISTS "${CIVETWEB_INCLUDE_DIR}/civetweb.h") - file(STRINGS "${CIVETWEB_INCLUDE_DIR}/civetweb.h" civetweb_version_str REGEX "^#define[\t ]+CIVETWEB_VERSION[\t ]+\".*\"") - - string(REGEX REPLACE "^.*CIVETWEB_VERSION[\t ]+\"([^\"]*)\".*$" "\\1" CIVETWEB_VERSION_STRING "${civetweb_version_str}") - unset(civetweb_version_str) -endif() - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(civetweb - FOUND_VAR civetweb_FOUND - REQUIRED_VARS CIVETWEB_LIBRARY CIVETWEB_CXX_LIBRARY CIVETWEB_INCLUDE_DIR CIVETWEB_CXX_INCLUDE_DIR - VERSION_VAR CIVETWEB_VERSION_STRING) - -if(civetweb_FOUND) - set(CIVETWEB_LIBRARIES civetweb::civetweb civetweb::civetweb-cpp) - set(CIVETWEB_INCLUDE_DIRS "${CIVETWEB_INCLUDE_DIR}" "${CIVETWEB_CXX_INCLUDE_DIR}") - if(NOT TARGET civetweb::civetweb) - add_library(civetweb::civetweb UNKNOWN IMPORTED) - set_target_properties(civetweb::civetweb PROPERTIES - IMPORTED_LOCATION "${CIVETWEB_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${CIVETWEB_INCLUDE_DIR}" - IMPORTED_LINK_INTERFACE_LANGUAGES "C" - ) - endif() - if(NOT TARGET civetweb::civetweb-cpp) - add_library(civetweb::civetweb-cpp UNKNOWN IMPORTED) - set_target_properties(civetweb::civetweb-cpp PROPERTIES - IMPORTED_LOCATION "${CIVETWEB_CXX_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${CIVETWEB_CXX_INCLUDE_DIR}" - IMPORTED_LINK_INTERFACE_LIBRARIES "civetweb::civetweb" - IMPORTED_LINK_INTERFACE_LANGUAGES "CXX" - ) - endif() -endif() diff --git a/pull/CMakeLists.txt b/pull/CMakeLists.txt index c940e5fe..7b3986d4 100644 --- a/pull/CMakeLists.txt +++ b/pull/CMakeLists.txt @@ -2,7 +2,7 @@ if(USE_THIRDPARTY_LIBRARIES) find_package(civetweb-3rdparty CONFIG REQUIRED) else() - find_package(civetweb REQUIRED) + find_package(civetweb CONFIG REQUIRED) endif() if(ENABLE_COMPRESSION) @@ -23,7 +23,7 @@ target_link_libraries(pull ${PROJECT_NAME}::core PRIVATE Threads::Threads - ${CIVETWEB_LIBRARIES} + $<$>:civetweb::civetweb-cpp> $<$,$>>:rt> $<$:ZLIB::ZLIB> ) From c06e0ef4e46a4770faa10210d41974df1fa12941 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Mon, 16 Mar 2020 15:43:55 +0100 Subject: [PATCH 076/206] pull: Add support for https and client certificates Issue: #329 --- CMakeLists.txt | 3 ++- cmake/civetweb-3rdparty-config.cmake | 13 ++++++++++++- cmake/prometheus-cpp-config.cmake.in | 12 ++++++++++++ pull/CMakeLists.txt | 4 +--- pull/include/prometheus/exposer.h | 2 ++ pull/src/exposer.cc | 11 ++++++++--- 6 files changed, 37 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 73f942cf..b95e515c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ -cmake_minimum_required(VERSION 3.5 FATAL_ERROR) +cmake_minimum_required(VERSION 3.12 FATAL_ERROR) project(prometheus-cpp VERSION 0.9.0) @@ -15,6 +15,7 @@ option(ENABLE_PUSH "Build prometheus-cpp push library" ON) option(ENABLE_COMPRESSION "Enable gzip compression" ON) option(ENABLE_TESTING "Build tests" ON) option(USE_THIRDPARTY_LIBRARIES "Use 3rdParty submodules" ON) +option(THIRDPARTY_CIVETWEB_WITH_SSL "Enable SSL support for embedded civetweb source code") option(OVERRIDE_CXX_STANDARD_FLAGS "Force building with -std=c++11 even if the CXXLFAGS are configured differently" ON) if(OVERRIDE_CXX_STANDARD_FLAGS) diff --git a/cmake/civetweb-3rdparty-config.cmake b/cmake/civetweb-3rdparty-config.cmake index 8e20fef1..d684361d 100644 --- a/cmake/civetweb-3rdparty-config.cmake +++ b/cmake/civetweb-3rdparty-config.cmake @@ -26,7 +26,6 @@ target_compile_definitions(civetweb NDEBUG NO_CGI NO_CACHING - NO_SSL NO_FILES ) @@ -41,6 +40,18 @@ target_include_directories(civetweb ${CIVETWEB_INCLUDE_DIRS} ) +if(THIRDPARTY_CIVETWEB_WITH_SSL) + include(CMakeFindDependencyMacro) + find_dependency(OpenSSL) + if(OPENSSL_VERSION VERSION_GREATER_EQUAL 1.1) + target_compile_definitions(civetweb PRIVATE OPENSSL_API_1_1) + endif() + target_compile_definitions(civetweb PRIVATE NO_SSL_DL) + target_link_libraries(civetweb PUBLIC OpenSSL::SSL) +else() + target_compile_definitions(civetweb PRIVATE NO_SSL) +endif() + if(BUILD_SHARED_LIBS) set_target_properties(civetweb PROPERTIES POSITION_INDEPENDENT_CODE ON diff --git a/cmake/prometheus-cpp-config.cmake.in b/cmake/prometheus-cpp-config.cmake.in index 9c64914e..fe9606e0 100644 --- a/cmake/prometheus-cpp-config.cmake.in +++ b/cmake/prometheus-cpp-config.cmake.in @@ -6,11 +6,23 @@ set_and_check(prometheus-cpp_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@") set(PROMETHEUS_CPP_ENABLE_PULL @ENABLE_PULL@) set(PROMETHEUS_CPP_ENABLE_PUSH @ENABLE_PUSH@) set(PROMETHEUS_CPP_USE_COMPRESSION @ENABLE_COMPRESSION@) +set(PROMETHEUS_CPP_USE_THIRDPARTY_LIBRARIES @USE_THIRDPARTY_LIBRARIES@) +set(PROMETHEUS_CPP_THIRDPARTY_CIVETWEB_WITH_SSL @THIRDPARTY_CIVETWEB_WITH_SSL@) set(CMAKE_THREAD_PREFER_PTHREAD TRUE) find_dependency(Threads) unset(CMAKE_THREAD_PREFER_PTHREAD) +if(PROMETHEUS_CPP_ENABLE_PULL) + if(PROMETHEUS_CPP_USE_THIRDPARTY_LIBRARIES) + if(PROMETHEUS_CPP_THIRDPARTY_CIVETWEB_WITH_SSL) + find_dependency(OpenSSL) + endif() + else() + find_dependency(civetweb) + endif() +endif() + if(PROMETHEUS_CPP_ENABLE_PULL AND PROMETHEUS_CPP_USE_COMPRESSION) find_dependency(ZLIB) endif() diff --git a/pull/CMakeLists.txt b/pull/CMakeLists.txt index 7b3986d4..250390a7 100644 --- a/pull/CMakeLists.txt +++ b/pull/CMakeLists.txt @@ -1,4 +1,3 @@ - if(USE_THIRDPARTY_LIBRARIES) find_package(civetweb-3rdparty CONFIG REQUIRED) else() @@ -13,7 +12,6 @@ add_library(pull src/exposer.cc src/handler.cc src/handler.h - $<$:$> ) add_library(${PROJECT_NAME}::pull ALIAS pull) @@ -23,7 +21,7 @@ target_link_libraries(pull ${PROJECT_NAME}::core PRIVATE Threads::Threads - $<$>:civetweb::civetweb-cpp> + $,civetweb,civetweb::civetweb-cpp> $<$,$>>:rt> $<$:ZLIB::ZLIB> ) diff --git a/pull/include/prometheus/exposer.h b/pull/include/prometheus/exposer.h index 0917ba98..f58cfb3d 100644 --- a/pull/include/prometheus/exposer.h +++ b/pull/include/prometheus/exposer.h @@ -23,6 +23,8 @@ class PROMETHEUS_CPP_PULL_EXPORT Exposer { explicit Exposer(const std::string& bind_address, const std::string& uri = std::string("/metrics"), const std::size_t num_threads = 2); + explicit Exposer(std::vector options, + const std::string& uri = std::string("/metrics")); ~Exposer(); void RegisterCollectable(const std::weak_ptr& collectable); diff --git a/pull/src/exposer.cc b/pull/src/exposer.cc index ad22b7e0..7e97b14e 100644 --- a/pull/src/exposer.cc +++ b/pull/src/exposer.cc @@ -5,6 +5,7 @@ #include #include "prometheus/client_metric.h" +#include "prometheus/detail/future_std.h" #include "CivetServer.h" #include "handler.h" @@ -13,9 +14,13 @@ namespace prometheus { Exposer::Exposer(const std::string& bind_address, const std::string& uri, const std::size_t num_threads) - : server_(new CivetServer{std::vector{ - "listening_ports", bind_address, "num_threads", - std::to_string(num_threads)}}), + : Exposer( + std::vector{"listening_ports", bind_address, + "num_threads", std::to_string(num_threads)}, + uri) {} + +Exposer::Exposer(std::vector options, const std::string& uri) + : server_(detail::make_unique(std::move(options))), exposer_registry_(std::make_shared()), metrics_handler_( new detail::MetricsHandler{collectables_, *exposer_registry_}), From 23d67fd9ae4e1ed8795597d153f3f858e87a66da Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Wed, 18 Mar 2020 09:05:19 +0100 Subject: [PATCH 077/206] chore: Use civetweb 1.12 --- 3rdparty/civetweb | 2 +- bazel/repositories.bzl | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/3rdparty/civetweb b/3rdparty/civetweb index ce8f6d38..4b440a33 160000 --- a/3rdparty/civetweb +++ b/3rdparty/civetweb @@ -1 +1 @@ -Subproject commit ce8f6d38a60eb16c996afee1e5340f76ef4d0923 +Subproject commit 4b440a339979852d5a51fb11a822952712231c23 diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index e2d0e0ba..005e3cf6 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -5,10 +5,10 @@ def prometheus_cpp_repositories(): maybe( http_archive, name = "civetweb", - strip_prefix = "civetweb-2c1caa6e690bfe3b435a10c372ab2dcd14b872e8", - sha256 = "d576b2257fe116523e5644232868670dcdd6c89b8e42b69d51e26b146575ab6a", + strip_prefix = "civetweb-1.12", + sha256 = "8cab1e2ad8fb3e2e81fed0b2321a5afbd7269a644c44ed4c3607e0a212c6d9e1", urls = [ - "https://github.com/civetweb/civetweb/archive/2c1caa6e690bfe3b435a10c372ab2dcd14b872e8.tar.gz", + "https://github.com/civetweb/civetweb/archive/v1.12.tar.gz", ], build_file = "@com_github_jupp0r_prometheus_cpp//bazel:civetweb.BUILD", ) From eef4b55b27709ae48cba84c544ee4e25d91e41fb Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Fri, 20 Mar 2020 16:38:30 +0100 Subject: [PATCH 078/206] fix: Properly export civetweb object library --- pull/CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pull/CMakeLists.txt b/pull/CMakeLists.txt index 250390a7..64feaa8f 100644 --- a/pull/CMakeLists.txt +++ b/pull/CMakeLists.txt @@ -1,5 +1,10 @@ if(USE_THIRDPARTY_LIBRARIES) find_package(civetweb-3rdparty CONFIG REQUIRED) + add_library(${PROJECT_NAME}::civetweb ALIAS civetweb) + install( + TARGETS civetweb + EXPORT ${PROJECT_NAME}-targets + ) else() find_package(civetweb CONFIG REQUIRED) endif() @@ -21,7 +26,7 @@ target_link_libraries(pull ${PROJECT_NAME}::core PRIVATE Threads::Threads - $,civetweb,civetweb::civetweb-cpp> + $,${PROJECT_NAME}::civetweb,civetweb::civetweb-cpp> $<$,$>>:rt> $<$:ZLIB::ZLIB> ) From ad7438bacf641abe3e20efe74276e70bb777c83a Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Fri, 20 Mar 2020 18:16:18 +0100 Subject: [PATCH 079/206] feat: Add project to test CMake export --- .github/scripts/run-cmake-test | 16 ++++++++++++---- cmake/project-import/CMakeLists.txt | 17 +++++++++++++++++ cmake/project-import/sample_client.cc | 1 + cmake/project-import/sample_server.cc | 1 + 4 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 cmake/project-import/CMakeLists.txt create mode 120000 cmake/project-import/sample_client.cc create mode 120000 cmake/project-import/sample_server.cc diff --git a/.github/scripts/run-cmake-test b/.github/scripts/run-cmake-test index 49a94a52..d5cae35e 100755 --- a/.github/scripts/run-cmake-test +++ b/.github/scripts/run-cmake-test @@ -7,17 +7,25 @@ WORKSPACE=$(cd "$(dirname "${BASH_SOURCE[0]}")"/../.. && /bin/pwd -P) # Build with internal dependencies mkdir "${WORKSPACE}/_build_internal_deps" && cd $_ -cmake .. -DUSE_THIRDPARTY_LIBRARIES=ON -DENABLE_WARNINGS_AS_ERRORS=ON -DENABLE_COMPRESSION=OFF -DENABLE_PUSH=OFF -make -j$(nproc) +cmake -DUSE_THIRDPARTY_LIBRARIES=ON -DENABLE_WARNINGS_AS_ERRORS=ON -DENABLE_COMPRESSION=OFF -DENABLE_PUSH=OFF "${WORKSPACE}" +make -j$(getconf _NPROCESSORS_ONLN) ctest -V mkdir -p deploy make DESTDIR="${PWD}/deploy" install +mkdir "${WORKSPACE}/_import_internal_deps" && cd $_ +cmake "-Dprometheus-cpp_DIR=${WORKSPACE}/_build_internal_deps/deploy/usr/local/lib/cmake/prometheus-cpp" "${WORKSPACE}/cmake/project-import" +make -j$(getconf _NPROCESSORS_ONLN) + # Build with external dependencies mkdir "${WORKSPACE}/_build" && cd $_ -cmake .. -DUSE_THIRDPARTY_LIBRARIES=OFF "-DCMAKE_TOOLCHAIN_FILE=${VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake" -make -j$(nproc) +cmake -DUSE_THIRDPARTY_LIBRARIES=OFF "-DCMAKE_TOOLCHAIN_FILE=${VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake" "${WORKSPACE}" +make -j$(getconf _NPROCESSORS_ONLN) ctest -V -LE Benchmark mkdir -p deploy make DESTDIR="${PWD}/deploy" install + +mkdir "${WORKSPACE}/_import" && cd $_ +cmake "-DCMAKE_TOOLCHAIN_FILE=${VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake" "-Dprometheus-cpp_DIR=${WORKSPACE}/_build/deploy/usr/local/lib/cmake/prometheus-cpp" "${WORKSPACE}/cmake/project-import" +make -j$(getconf _NPROCESSORS_ONLN) diff --git a/cmake/project-import/CMakeLists.txt b/cmake/project-import/CMakeLists.txt new file mode 100644 index 00000000..6fb0c6c9 --- /dev/null +++ b/cmake/project-import/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.12 FATAL_ERROR) + +project(prometheus-cpp-import) + +set(CMAKE_CXX_STANDARD 11) + +find_package(prometheus-cpp CONFIG REQUIRED) + +if(PROMETHEUS_CPP_ENABLE_PUSH) + add_executable(sample-client sample_client.cc) + target_link_libraries(sample-client PRIVATE prometheus-cpp::push) +endif() + +if(PROMETHEUS_CPP_ENABLE_PULL) + add_executable(sample-server sample_server.cc) + target_link_libraries(sample-server PRIVATE prometheus-cpp::pull) +endif() diff --git a/cmake/project-import/sample_client.cc b/cmake/project-import/sample_client.cc new file mode 120000 index 00000000..4c67af80 --- /dev/null +++ b/cmake/project-import/sample_client.cc @@ -0,0 +1 @@ +../../push/tests/integration/sample_client.cc \ No newline at end of file diff --git a/cmake/project-import/sample_server.cc b/cmake/project-import/sample_server.cc new file mode 120000 index 00000000..89f9e5c0 --- /dev/null +++ b/cmake/project-import/sample_server.cc @@ -0,0 +1 @@ +../../pull/tests/integration/sample_server.cc \ No newline at end of file From fa6299d771044e0e91b31f772a344eec322ad850 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Fri, 20 Mar 2020 20:30:15 +0100 Subject: [PATCH 080/206] chore: use imported CMake curl target --- push/CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/push/CMakeLists.txt b/push/CMakeLists.txt index 721386d1..81e606f1 100644 --- a/push/CMakeLists.txt +++ b/push/CMakeLists.txt @@ -12,7 +12,7 @@ target_link_libraries(push ${PROJECT_NAME}::core PRIVATE Threads::Threads - ${CURL_LIBRARIES} + CURL::libcurl $<$,$>>:rt> ) @@ -20,8 +20,6 @@ target_include_directories(push PUBLIC $ $ - PRIVATE - ${CURL_INCLUDE_DIRS} ) set_target_properties(push From 05ad99930c3fdec84c6676558c2a727f3de22ac7 Mon Sep 17 00:00:00 2001 From: Stephen Bates Date: Thu, 23 Apr 2020 15:09:41 -0600 Subject: [PATCH 081/206] CMake: Fix directory permissions on installation This patch sets the default permission for installed directories as 755, using variable CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS, which was introduced in CMake 3.11. Note that not setting this variable leads to platform specific behaviour which can change from user to user. Fixes #361 --- CMakeLists.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index b95e515c..1157ea49 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,16 @@ if(OVERRIDE_CXX_STANDARD_FLAGS) set(CMAKE_CXX_EXTENSIONS Off) endif() +# Set default directory permissions +set(CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS + OWNER_READ + OWNER_WRITE + OWNER_EXECUTE + GROUP_READ + GROUP_EXECUTE + WORLD_READ + WORLD_EXECUTE) + # Put DLLs and binaries into same directory set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) From 82a0982d97cfafe04c85c7f6376f591e41f09408 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 25 Apr 2020 14:36:35 +0200 Subject: [PATCH 082/206] Add reason for setting CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1157ea49..79a10aea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,9 @@ if(OVERRIDE_CXX_STANDARD_FLAGS) set(CMAKE_CXX_EXTENSIONS Off) endif() -# Set default directory permissions +# Set default directory permissions until +# https://gitlab.kitware.com/cmake/cmake/issues/15163 +# is fixed set(CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS OWNER_READ OWNER_WRITE From 06b1fe03f6832e09fac04e12d487d71cb9b4600f Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 25 Apr 2020 15:15:34 +0200 Subject: [PATCH 083/206] doc: Add brief instructions how to consume Closes: #359 --- README.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/README.md b/README.md index 55cbb7e1..7a14aa0e 100644 --- a/README.md +++ b/README.md @@ -171,6 +171,36 @@ This will place an appropriately named .deb in the `_build` folder. To build a RPM package set the `CPACK_GENERATOR` variable to `RPM`. +## Consuming the installed project + +### CMake + +Consuming prometheus-cpp via CMake is the preferred way because all the dependencies +between the three prometheus-cpp libraries are handled correctly. + +The `cmake/project-import` directory contains an +example project and minimal [CMakeLists.txt](cmake/project-import/CMakeLists.txt). + +### vcpkg + +The [vcpkg](https://github.com/microsoft/vcpkg) package manager contains a +prometheus-cpp port which has been tested on Linux, macOS, and Windows. + +### Plain Makefiles + +When manually linking prometheus-cpp the library order matters. The needed +libraries depend on the individual use case but the following should work for the pull metrics approach: + +``` +-lprometheus-cpp-pull -lprometheus-cpp-core -lz +``` + +For the push-workflow please try: + +``` +-lprometheus-cpp-push -lprometheus-cpp-core -lcurl -lz +``` + ## Contributing Please adhere to the [Google C++ Style From 22a8f08c577295fdec5a76126906e6f9ac7fc240 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 25 Apr 2020 15:23:08 +0200 Subject: [PATCH 084/206] ci: Fix documentation generation --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4ebd2f52..bc2d87c5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ sudo: required -dist: xenial +dist: bionic language: c++ env: @@ -12,6 +12,7 @@ addons: apt: packages: - doxygen + - graphviz script: - pushd . From 6dd2c7cba70705287bffa62c0a9ce1f5fb13ff27 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 25 Apr 2020 15:30:57 +0200 Subject: [PATCH 085/206] doc: Use README.md as mainpage --- doc/Doxyfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/Doxyfile b/doc/Doxyfile index d616c2a6..14a657e4 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -5,8 +5,9 @@ EXCLUDE_SYMBOLS = prometheus::detail::* FILE_PATTERNS = *.h *.cc GENERATE_LATEX = NO GRAPHICAL_HIERARCHY = NO -INPUT = ../core/include ../core/src ../pull/include ../pull/src ../push/include ../push/src +INPUT = ../README.md ../core/include ../core/src ../pull/include ../pull/src ../push/include ../push/src RECURSIVE = YES SHOW_FILES = NO SHOW_INCLUDE_FILES = NO SHOW_USED_FILES = NO +USE_MDFILE_AS_MAINPAGE = ../README.md From 4ee54a16519d571d508e0268b6aeb85f0689fc8b Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 25 Apr 2020 15:50:34 +0200 Subject: [PATCH 086/206] chore(pull): refactor collection code into metrics_collector --- pull/CMakeLists.txt | 2 ++ pull/src/handler.cc | 21 ++------------------- pull/src/handler.h | 2 -- pull/src/metrics_collector.cc | 28 ++++++++++++++++++++++++++++ pull/src/metrics_collector.h | 14 ++++++++++++++ 5 files changed, 46 insertions(+), 21 deletions(-) create mode 100644 pull/src/metrics_collector.cc create mode 100644 pull/src/metrics_collector.h diff --git a/pull/CMakeLists.txt b/pull/CMakeLists.txt index 64feaa8f..d278ba99 100644 --- a/pull/CMakeLists.txt +++ b/pull/CMakeLists.txt @@ -17,6 +17,8 @@ add_library(pull src/exposer.cc src/handler.cc src/handler.h + src/metrics_collector.cc + src/metrics_collector.h ) add_library(${PROJECT_NAME}::pull ALIAS pull) diff --git a/pull/src/handler.cc b/pull/src/handler.cc index ea94365a..9ba95442 100644 --- a/pull/src/handler.cc +++ b/pull/src/handler.cc @@ -3,12 +3,12 @@ #include "prometheus/summary.h" #include -#include #ifdef HAVE_ZLIB #include #endif +#include "metrics_collector.h" #include "prometheus/serializer.h" #include "prometheus/text_serializer.h" @@ -118,7 +118,7 @@ static std::size_t WriteResponse(struct mg_connection* conn, bool MetricsHandler::handleGet(CivetServer*, struct mg_connection* conn) { auto start_time_of_request = std::chrono::steady_clock::now(); - auto metrics = CollectMetrics(); + auto metrics = CollectMetrics(collectables_); auto serializer = std::unique_ptr{new TextSerializer()}; @@ -133,22 +133,5 @@ bool MetricsHandler::handleGet(CivetServer*, struct mg_connection* conn) { num_scrapes_.Increment(); return true; } -std::vector MetricsHandler::CollectMetrics() const { - auto collected_metrics = std::vector{}; - - for (auto&& wcollectable : collectables_) { - auto collectable = wcollectable.lock(); - if (!collectable) { - continue; - } - - auto&& metrics = collectable->Collect(); - collected_metrics.insert(collected_metrics.end(), - std::make_move_iterator(metrics.begin()), - std::make_move_iterator(metrics.end())); - } - - return collected_metrics; -} } // namespace detail } // namespace prometheus diff --git a/pull/src/handler.h b/pull/src/handler.h index 112267aa..f28f7f57 100644 --- a/pull/src/handler.h +++ b/pull/src/handler.h @@ -18,8 +18,6 @@ class MetricsHandler : public CivetHandler { bool handleGet(CivetServer* server, struct mg_connection* conn) override; private: - std::vector CollectMetrics() const; - const std::vector>& collectables_; Family& bytes_transferred_family_; Counter& bytes_transferred_; diff --git a/pull/src/metrics_collector.cc b/pull/src/metrics_collector.cc new file mode 100644 index 00000000..4235e6fd --- /dev/null +++ b/pull/src/metrics_collector.cc @@ -0,0 +1,28 @@ +#include "metrics_collector.h" + +#include "prometheus/collectable.h" + +namespace prometheus { +namespace detail { + +std::vector CollectMetrics( + const std::vector>& collectables) { + auto collected_metrics = std::vector{}; + + for (auto&& wcollectable : collectables) { + auto collectable = wcollectable.lock(); + if (!collectable) { + continue; + } + + auto&& metrics = collectable->Collect(); + collected_metrics.insert(collected_metrics.end(), + std::make_move_iterator(metrics.begin()), + std::make_move_iterator(metrics.end())); + } + + return collected_metrics; +} + +} // namespace detail +} // namespace prometheus diff --git a/pull/src/metrics_collector.h b/pull/src/metrics_collector.h new file mode 100644 index 00000000..4c3bb614 --- /dev/null +++ b/pull/src/metrics_collector.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +#include "prometheus/metric_family.h" + +namespace prometheus { +class Collectable; +namespace detail { +std::vector CollectMetrics( + const std::vector>& collectables); +} // namespace detail +} // namespace prometheus From 538e9d61ab23d3ef876c26010c02dc93eb98bc60 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Wed, 13 May 2020 14:34:24 +0200 Subject: [PATCH 087/206] ci: Use preinstalled Bazel --- .github/scripts/run-prepare | 16 ---------------- .github/scripts/run-prepare.cmd | 4 ---- 2 files changed, 20 deletions(-) diff --git a/.github/scripts/run-prepare b/.github/scripts/run-prepare index 4f266273..0fbe1045 100755 --- a/.github/scripts/run-prepare +++ b/.github/scripts/run-prepare @@ -10,11 +10,6 @@ case "${OS_ARG}" in packages=(locales) case "${BUILDSYSTEM_ARG}" in - bazel) - curl -sL https://bazel.build/bazel-release.pub.gpg | sudo apt-key add - - echo "deb [arch=amd64] https://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list - packages+=(bazel) - ;; cmake) packages+=(python-pip python-wheel) ;; @@ -33,22 +28,11 @@ case "${OS_ARG}" in macOS*) packages=(prometheus telegraf) - - case "${BUILDSYSTEM_ARG}" in - bazel) - packages+=(bazelbuild/tap/bazel) - ;; - cmake) - ;; - esac - brew install "${packages[@]}" ;; esac case "${BUILDSYSTEM_ARG}" in - bazel) - ;; cmake) "${VCPKG_INSTALLATION_ROOT}/vcpkg" install benchmark civetweb curl gtest zlib ;; diff --git a/.github/scripts/run-prepare.cmd b/.github/scripts/run-prepare.cmd index f4d2b1ef..ec14d92f 100644 --- a/.github/scripts/run-prepare.cmd +++ b/.github/scripts/run-prepare.cmd @@ -1,7 +1,3 @@ -if [%1] == [bazel] ( - choco install bazel -y || EXIT /B 1 -) - if [%1] == [cmake] ( %VCPKG_INSTALLATION_ROOT%/vcpkg install benchmark civetweb curl gtest zlib || EXIT /B 1 ) From cc282f998555bcdfafea2749cef132d794aece9a Mon Sep 17 00:00:00 2001 From: James Harrison <00jamesh@gmail.com> Date: Thu, 30 Apr 2020 14:25:42 +0100 Subject: [PATCH 088/206] Add support for serving multiple paths Allows users to specify multiple Endpoints, and register Collectables to each Endpoint. E.g., /metrics and /metricsHighCardinality Can both be served by the same MultiExposer, but may expose different Collectables. This may be useful if, for example, one wants to scrape groups of metrics with different frequencies. Each Endpoint must have a unique URI. --- pull/CMakeLists.txt | 1 + pull/include/prometheus/endpoint.h | 34 +++++++++++ pull/include/prometheus/exposer.h | 43 ++++++++++---- pull/src/endpoint.cc | 28 +++++++++ pull/src/exposer.cc | 48 ++++++++++------ pull/tests/integration/BUILD.bazel | 6 ++ pull/tests/integration/CMakeLists.txt | 10 ++++ pull/tests/integration/sample_server_multi.cc | 57 +++++++++++++++++++ 8 files changed, 199 insertions(+), 28 deletions(-) create mode 100644 pull/include/prometheus/endpoint.h create mode 100644 pull/src/endpoint.cc create mode 100644 pull/tests/integration/sample_server_multi.cc diff --git a/pull/CMakeLists.txt b/pull/CMakeLists.txt index d278ba99..cb8f1688 100644 --- a/pull/CMakeLists.txt +++ b/pull/CMakeLists.txt @@ -14,6 +14,7 @@ if(ENABLE_COMPRESSION) endif() add_library(pull + src/endpoint.cc src/exposer.cc src/handler.cc src/handler.h diff --git a/pull/include/prometheus/endpoint.h b/pull/include/prometheus/endpoint.h new file mode 100644 index 00000000..b3f8b900 --- /dev/null +++ b/pull/include/prometheus/endpoint.h @@ -0,0 +1,34 @@ +#pragma once + +#include + +#include "prometheus/collectable.h" +#include "prometheus/detail/pull_export.h" +#include "prometheus/registry.h" + +namespace prometheus { + +namespace detail { +class MetricsHandler; +} // namespace detail + +class PROMETHEUS_CPP_PULL_EXPORT Endpoint { + public: + explicit Endpoint(std::string uri); + ~Endpoint(); + + void RegisterCollectable(const std::weak_ptr& collectable); + + detail::MetricsHandler* getMetricsHandler() const; + + const std::string& getURI() const; + + private: + std::vector> collectables_; + // registry for "meta" metrics about the endpoint itself + std::shared_ptr endpoint_registry_; + std::unique_ptr metrics_handler_; + std::string uri_; +}; + +} // namespace prometheus diff --git a/pull/include/prometheus/exposer.h b/pull/include/prometheus/exposer.h index f58cfb3d..26369cbb 100644 --- a/pull/include/prometheus/exposer.h +++ b/pull/include/prometheus/exposer.h @@ -18,24 +18,45 @@ namespace detail { class MetricsHandler; } // namespace detail -class PROMETHEUS_CPP_PULL_EXPORT Exposer { +class Endpoint; + +/** + * Exposer capable of serving different groups of Collectables + * on different paths. + */ +class PROMETHEUS_CPP_PULL_EXPORT MultiExposer { + public: + MultiExposer(const std::string& bind_address, + std::vector> endpoints, + const std::size_t num_threads = 2); + + MultiExposer(std::vector options, + std::vector> endpoints); + + virtual ~MultiExposer(); + + std::vector GetListeningPorts() const; + + protected: + std::unique_ptr server_; + std::vector> endpoints_; +}; + +/** + * Exposer serving a group of Collectables on a single path. + * + * Provides a simpler interface than directly using a MultiExposer with + * a single Endpoint. + */ +class PROMETHEUS_CPP_PULL_EXPORT Exposer : public MultiExposer { public: explicit Exposer(const std::string& bind_address, const std::string& uri = std::string("/metrics"), const std::size_t num_threads = 2); explicit Exposer(std::vector options, const std::string& uri = std::string("/metrics")); - ~Exposer(); - void RegisterCollectable(const std::weak_ptr& collectable); - std::vector GetListeningPorts() const; - - private: - std::unique_ptr server_; - std::vector> collectables_; - std::shared_ptr exposer_registry_; - std::unique_ptr metrics_handler_; - std::string uri_; + void RegisterCollectable(const std::weak_ptr& collectable); }; } // namespace prometheus diff --git a/pull/src/endpoint.cc b/pull/src/endpoint.cc new file mode 100644 index 00000000..902e79b3 --- /dev/null +++ b/pull/src/endpoint.cc @@ -0,0 +1,28 @@ +#include "prometheus/endpoint.h" + +#include "handler.h" + +namespace prometheus { + +Endpoint::Endpoint(std::string uri) + : endpoint_registry_(std::make_shared()), + metrics_handler_( + new detail::MetricsHandler{collectables_, *endpoint_registry_}), + uri_(std::move(uri)) { + RegisterCollectable(endpoint_registry_); +} + +Endpoint::~Endpoint() = default; + +void Endpoint::RegisterCollectable( + const std::weak_ptr& collectable) { + collectables_.push_back(collectable); +} + +detail::MetricsHandler* Endpoint::getMetricsHandler() const { + return metrics_handler_.get(); +} + +const std::string& Endpoint::getURI() const { return uri_; } + +} // namespace prometheus diff --git a/pull/src/exposer.cc b/pull/src/exposer.cc index 7e97b14e..250e9acc 100644 --- a/pull/src/exposer.cc +++ b/pull/src/exposer.cc @@ -6,38 +6,52 @@ #include "prometheus/client_metric.h" #include "prometheus/detail/future_std.h" +#include "prometheus/endpoint.h" #include "CivetServer.h" #include "handler.h" namespace prometheus { -Exposer::Exposer(const std::string& bind_address, const std::string& uri, - const std::size_t num_threads) - : Exposer( +MultiExposer::MultiExposer(const std::string& bind_address, + std::vector> endpoints, + const std::size_t num_threads) + : MultiExposer( std::vector{"listening_ports", bind_address, "num_threads", std::to_string(num_threads)}, - uri) {} + std::move(endpoints)) {} -Exposer::Exposer(std::vector options, const std::string& uri) +MultiExposer::MultiExposer(std::vector options, + std::vector> endpoints) : server_(detail::make_unique(std::move(options))), - exposer_registry_(std::make_shared()), - metrics_handler_( - new detail::MetricsHandler{collectables_, *exposer_registry_}), - uri_(uri) { - RegisterCollectable(exposer_registry_); - server_->addHandler(uri, metrics_handler_.get()); + endpoints_(std::move(endpoints)) { + for (const auto& endpoint : endpoints_) { + server_->addHandler(endpoint->getURI(), endpoint->getMetricsHandler()); + } } -Exposer::~Exposer() { server_->removeHandler(uri_); } - -void Exposer::RegisterCollectable( - const std::weak_ptr& collectable) { - collectables_.push_back(collectable); +MultiExposer::~MultiExposer() { + for (const auto& endpoint : endpoints_) { + server_->removeHandler(endpoint->getURI()); + } } -std::vector Exposer::GetListeningPorts() const { +std::vector MultiExposer::GetListeningPorts() const { return server_->getListeningPorts(); } +Exposer::Exposer(const std::string& bind_address, const std::string& uri, + const std::size_t num_threads) + : MultiExposer(bind_address, {std::make_shared(uri)}, + num_threads) {} + +Exposer::Exposer(std::vector options, const std::string& uri) + : MultiExposer(std::move(options), {std::make_shared(uri)}) {} + +void Exposer::RegisterCollectable( + const std::weak_ptr& collectable) { + // Exposer is guaranteed to have a single Endpoint. + endpoints_.at(0)->RegisterCollectable(collectable); +} + } // namespace prometheus diff --git a/pull/tests/integration/BUILD.bazel b/pull/tests/integration/BUILD.bazel index 4104a6a5..2e172af6 100644 --- a/pull/tests/integration/BUILD.bazel +++ b/pull/tests/integration/BUILD.bazel @@ -4,6 +4,12 @@ cc_binary( deps = ["//pull"], ) +cc_binary( + name = "sample-server_multi", + srcs = ["sample_server_multi.cc"], + deps = ["//pull"], +) + sh_test( name = "scrape-test", size = "small", diff --git a/pull/tests/integration/CMakeLists.txt b/pull/tests/integration/CMakeLists.txt index 1ba22cdc..ecf64aa1 100644 --- a/pull/tests/integration/CMakeLists.txt +++ b/pull/tests/integration/CMakeLists.txt @@ -7,3 +7,13 @@ target_link_libraries(sample_server PRIVATE ${PROJECT_NAME}::pull ) + + +add_executable(sample_server_multi + sample_server_multi.cc + ) + +target_link_libraries(sample_server_multi + PRIVATE + ${PROJECT_NAME}::pull + ) diff --git a/pull/tests/integration/sample_server_multi.cc b/pull/tests/integration/sample_server_multi.cc new file mode 100644 index 00000000..25de39eb --- /dev/null +++ b/pull/tests/integration/sample_server_multi.cc @@ -0,0 +1,57 @@ +#include +#include +#include +#include + +#include +#include +#include + +int main() { + using namespace prometheus; + + auto endpointA = std::make_shared("/metricsA"); + auto endpointB = std::make_shared("/metricsB"); + + auto registryA = std::make_shared(); + + // add a new counter family to the registry (families combine values with the + // same name, but distinct label dimensions) + auto& counter_familyA = BuildCounter() + .Name("time_running_seconds_total") + .Help("How many seconds is this server running?") + .Labels({{"label", "foo"}}) + .Register(*registryA); + + // add a counter to the metric family + auto& seconds_counterA = counter_familyA.Add( + {{"another_label", "bar"}, {"yet_another_label", "baz"}}); + + // ask the exposer to scrape registryA on incoming scrapes for "/metricsA" + endpointA->RegisterCollectable(registryA); + + auto registryB = std::make_shared(); + + auto& counter_familyB = BuildCounter() + .Name("other_time_running_seconds_total") + .Help("How many seconds has something else been running?") + .Labels({{"label", "not_foo"}}) + .Register(*registryB); + + auto& seconds_counterB = counter_familyB.Add( + {{"another_label", "not_bar"}, {"yet_another_label", "not_baz"}}); + + // This endpoint exposes registryB. + endpointB->RegisterCollectable(registryB); + + // create an http server running on port 8080 + MultiExposer exposer{"127.0.0.1:8080", {endpointA, endpointB}, 1}; + + for (;;) { + std::this_thread::sleep_for(std::chrono::seconds(1)); + // increment the counters by one (second) + seconds_counterA.Increment(); + seconds_counterB.Increment(); + } + return 0; +} From 8b45141a1c092eb7d1fb3260482fd8b5d7b842f2 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Mon, 25 May 2020 18:12:52 +0200 Subject: [PATCH 089/206] Extend existing exposer interface --- pull/CMakeLists.txt | 1 + pull/include/prometheus/exposer.h | 46 ++++---------- pull/src/endpoint.cc | 27 ++++---- pull/{include/prometheus => src}/endpoint.h | 21 ++++--- pull/src/exposer.cc | 63 ++++++++----------- pull/src/handler.cc | 5 +- pull/tests/integration/CMakeLists.txt | 11 ++-- pull/tests/integration/sample_server.cc | 10 +-- pull/tests/integration/sample_server_multi.cc | 27 ++++---- 9 files changed, 89 insertions(+), 122 deletions(-) rename pull/{include/prometheus => src}/endpoint.h (62%) diff --git a/pull/CMakeLists.txt b/pull/CMakeLists.txt index cb8f1688..bfdf1351 100644 --- a/pull/CMakeLists.txt +++ b/pull/CMakeLists.txt @@ -15,6 +15,7 @@ endif() add_library(pull src/endpoint.cc + src/endpoint.h src/exposer.cc src/handler.cc src/handler.h diff --git a/pull/include/prometheus/exposer.h b/pull/include/prometheus/exposer.h index 26369cbb..f8122f01 100644 --- a/pull/include/prometheus/exposer.h +++ b/pull/include/prometheus/exposer.h @@ -15,48 +15,26 @@ class CivetServer; namespace prometheus { namespace detail { +class Endpoint; class MetricsHandler; } // namespace detail -class Endpoint; - -/** - * Exposer capable of serving different groups of Collectables - * on different paths. - */ -class PROMETHEUS_CPP_PULL_EXPORT MultiExposer { +class PROMETHEUS_CPP_PULL_EXPORT Exposer { public: - MultiExposer(const std::string& bind_address, - std::vector> endpoints, - const std::size_t num_threads = 2); - - MultiExposer(std::vector options, - std::vector> endpoints); - - virtual ~MultiExposer(); + explicit Exposer(const std::string& bind_address, + const std::size_t num_threads = 2); + explicit Exposer(std::vector options); + ~Exposer(); + void RegisterCollectable(const std::weak_ptr& collectable, + const std::string& uri = std::string("/metrics")); std::vector GetListeningPorts() const; - protected: - std::unique_ptr server_; - std::vector> endpoints_; -}; + private: + detail::Endpoint& GetEndpointForUri(const std::string& uri); -/** - * Exposer serving a group of Collectables on a single path. - * - * Provides a simpler interface than directly using a MultiExposer with - * a single Endpoint. - */ -class PROMETHEUS_CPP_PULL_EXPORT Exposer : public MultiExposer { - public: - explicit Exposer(const std::string& bind_address, - const std::string& uri = std::string("/metrics"), - const std::size_t num_threads = 2); - explicit Exposer(std::vector options, - const std::string& uri = std::string("/metrics")); - - void RegisterCollectable(const std::weak_ptr& collectable); + std::unique_ptr server_; + std::vector> endpoints_; }; } // namespace prometheus diff --git a/pull/src/endpoint.cc b/pull/src/endpoint.cc index 902e79b3..c4e7ebc7 100644 --- a/pull/src/endpoint.cc +++ b/pull/src/endpoint.cc @@ -1,28 +1,29 @@ -#include "prometheus/endpoint.h" +#include "endpoint.h" #include "handler.h" +#include "prometheus/detail/future_std.h" namespace prometheus { - -Endpoint::Endpoint(std::string uri) - : endpoint_registry_(std::make_shared()), - metrics_handler_( - new detail::MetricsHandler{collectables_, *endpoint_registry_}), - uri_(std::move(uri)) { +namespace detail { + +Endpoint::Endpoint(CivetServer& server, std::string uri) + : server_(server), + uri_(std::move(uri)), + endpoint_registry_(std::make_shared()), + metrics_handler_(detail::make_unique( + collectables_, *endpoint_registry_)) { RegisterCollectable(endpoint_registry_); + server_.addHandler(uri_, metrics_handler_.get()); } -Endpoint::~Endpoint() = default; +Endpoint::~Endpoint() { server_.removeHandler(uri_); } void Endpoint::RegisterCollectable( const std::weak_ptr& collectable) { collectables_.push_back(collectable); } -detail::MetricsHandler* Endpoint::getMetricsHandler() const { - return metrics_handler_.get(); -} - -const std::string& Endpoint::getURI() const { return uri_; } +const std::string& Endpoint::GetURI() const { return uri_; } +} // namespace detail } // namespace prometheus diff --git a/pull/include/prometheus/endpoint.h b/pull/src/endpoint.h similarity index 62% rename from pull/include/prometheus/endpoint.h rename to pull/src/endpoint.h index b3f8b900..9b9c94bd 100644 --- a/pull/include/prometheus/endpoint.h +++ b/pull/src/endpoint.h @@ -1,34 +1,35 @@ #pragma once +#include #include +#include #include "prometheus/collectable.h" -#include "prometheus/detail/pull_export.h" #include "prometheus/registry.h" -namespace prometheus { +class CivetServer; +namespace prometheus { namespace detail { class MetricsHandler; -} // namespace detail -class PROMETHEUS_CPP_PULL_EXPORT Endpoint { +class Endpoint { public: - explicit Endpoint(std::string uri); + explicit Endpoint(CivetServer& server, std::string uri); ~Endpoint(); void RegisterCollectable(const std::weak_ptr& collectable); - detail::MetricsHandler* getMetricsHandler() const; - - const std::string& getURI() const; + const std::string& GetURI() const; private: + CivetServer& server_; + const std::string uri_; std::vector> collectables_; // registry for "meta" metrics about the endpoint itself std::shared_ptr endpoint_registry_; - std::unique_ptr metrics_handler_; - std::string uri_; + std::unique_ptr metrics_handler_; }; +} // namespace detail } // namespace prometheus diff --git a/pull/src/exposer.cc b/pull/src/exposer.cc index 250e9acc..a896b627 100644 --- a/pull/src/exposer.cc +++ b/pull/src/exposer.cc @@ -4,54 +4,45 @@ #include #include -#include "prometheus/client_metric.h" -#include "prometheus/detail/future_std.h" -#include "prometheus/endpoint.h" - #include "CivetServer.h" +#include "endpoint.h" #include "handler.h" +#include "prometheus/client_metric.h" +#include "prometheus/detail/future_std.h" namespace prometheus { -MultiExposer::MultiExposer(const std::string& bind_address, - std::vector> endpoints, - const std::size_t num_threads) - : MultiExposer( - std::vector{"listening_ports", bind_address, - "num_threads", std::to_string(num_threads)}, - std::move(endpoints)) {} - -MultiExposer::MultiExposer(std::vector options, - std::vector> endpoints) - : server_(detail::make_unique(std::move(options))), - endpoints_(std::move(endpoints)) { - for (const auto& endpoint : endpoints_) { - server_->addHandler(endpoint->getURI(), endpoint->getMetricsHandler()); - } -} +Exposer::Exposer(const std::string& bind_address, const std::size_t num_threads) + : Exposer(std::vector{"listening_ports", bind_address, + "num_threads", + std::to_string(num_threads)}) {} -MultiExposer::~MultiExposer() { - for (const auto& endpoint : endpoints_) { - server_->removeHandler(endpoint->getURI()); - } +Exposer::Exposer(std::vector options) + : server_(detail::make_unique(std::move(options))) {} + +Exposer::~Exposer() = default; + +void Exposer::RegisterCollectable(const std::weak_ptr& collectable, + const std::string& uri) { + auto& endpoint = GetEndpointForUri(uri); + endpoint.RegisterCollectable(collectable); } -std::vector MultiExposer::GetListeningPorts() const { +std::vector Exposer::GetListeningPorts() const { return server_->getListeningPorts(); } -Exposer::Exposer(const std::string& bind_address, const std::string& uri, - const std::size_t num_threads) - : MultiExposer(bind_address, {std::make_shared(uri)}, - num_threads) {} - -Exposer::Exposer(std::vector options, const std::string& uri) - : MultiExposer(std::move(options), {std::make_shared(uri)}) {} +detail::Endpoint& Exposer::GetEndpointForUri(const std::string& uri) { + auto sameUri = [uri](const std::unique_ptr& endpoint) { + return endpoint->GetURI() == uri; + }; + auto it = std::find_if(std::begin(endpoints_), std::end(endpoints_), sameUri); + if (it != std::end(endpoints_)) { + return *it->get(); + } -void Exposer::RegisterCollectable( - const std::weak_ptr& collectable) { - // Exposer is guaranteed to have a single Endpoint. - endpoints_.at(0)->RegisterCollectable(collectable); + endpoints_.emplace_back(detail::make_unique(*server_, uri)); + return *endpoints_.back().get(); } } // namespace prometheus diff --git a/pull/src/handler.cc b/pull/src/handler.cc index 9ba95442..eaad7420 100644 --- a/pull/src/handler.cc +++ b/pull/src/handler.cc @@ -1,9 +1,10 @@ #include "handler.h" -#include "prometheus/counter.h" -#include "prometheus/summary.h" #include +#include "prometheus/counter.h" +#include "prometheus/summary.h" + #ifdef HAVE_ZLIB #include #endif diff --git a/pull/tests/integration/CMakeLists.txt b/pull/tests/integration/CMakeLists.txt index ecf64aa1..82e41d08 100644 --- a/pull/tests/integration/CMakeLists.txt +++ b/pull/tests/integration/CMakeLists.txt @@ -8,12 +8,11 @@ target_link_libraries(sample_server ${PROJECT_NAME}::pull ) - add_executable(sample_server_multi - sample_server_multi.cc - ) + sample_server_multi.cc +) target_link_libraries(sample_server_multi - PRIVATE - ${PROJECT_NAME}::pull - ) + PRIVATE + ${PROJECT_NAME}::pull +) diff --git a/pull/tests/integration/sample_server.cc b/pull/tests/integration/sample_server.cc index ab8c3df8..72512fa2 100644 --- a/pull/tests/integration/sample_server.cc +++ b/pull/tests/integration/sample_server.cc @@ -1,18 +1,18 @@ +#include +#include +#include + #include #include #include #include #include -#include -#include -#include - int main() { using namespace prometheus; // create an http server running on port 8080 - Exposer exposer{"127.0.0.1:8080", "/metrics", 1}; + Exposer exposer{"127.0.0.1:8080", 1}; // create a metrics registry with component=main labels applied to all its // metrics diff --git a/pull/tests/integration/sample_server_multi.cc b/pull/tests/integration/sample_server_multi.cc index 25de39eb..4a86171a 100644 --- a/pull/tests/integration/sample_server_multi.cc +++ b/pull/tests/integration/sample_server_multi.cc @@ -1,5 +1,4 @@ #include -#include #include #include @@ -10,8 +9,8 @@ int main() { using namespace prometheus; - auto endpointA = std::make_shared("/metricsA"); - auto endpointB = std::make_shared("/metricsB"); + // create an http server running on port 8080 + Exposer exposer{"127.0.0.1:8080", 1}; auto registryA = std::make_shared(); @@ -20,7 +19,6 @@ int main() { auto& counter_familyA = BuildCounter() .Name("time_running_seconds_total") .Help("How many seconds is this server running?") - .Labels({{"label", "foo"}}) .Register(*registryA); // add a counter to the metric family @@ -28,30 +26,27 @@ int main() { {{"another_label", "bar"}, {"yet_another_label", "baz"}}); // ask the exposer to scrape registryA on incoming scrapes for "/metricsA" - endpointA->RegisterCollectable(registryA); + exposer.RegisterCollectable(registryA, "/metricsA"); auto registryB = std::make_shared(); - auto& counter_familyB = BuildCounter() - .Name("other_time_running_seconds_total") - .Help("How many seconds has something else been running?") - .Labels({{"label", "not_foo"}}) - .Register(*registryB); + auto& counter_familyB = + BuildCounter() + .Name("other_time_running_seconds_total") + .Help("How many seconds has something else been running?") + .Register(*registryB); auto& seconds_counterB = counter_familyB.Add( {{"another_label", "not_bar"}, {"yet_another_label", "not_baz"}}); // This endpoint exposes registryB. - endpointB->RegisterCollectable(registryB); - - // create an http server running on port 8080 - MultiExposer exposer{"127.0.0.1:8080", {endpointA, endpointB}, 1}; + exposer.RegisterCollectable(registryB, "/metricsB"); for (;;) { std::this_thread::sleep_for(std::chrono::seconds(1)); // increment the counters by one (second) - seconds_counterA.Increment(); - seconds_counterB.Increment(); + seconds_counterA.Increment(1.0); + seconds_counterB.Increment(1.5); } return 0; } From 5e1cfe72d207c28003a2a30f514e91aa1a67d170 Mon Sep 17 00:00:00 2001 From: James Harrison <00jamesh@gmail.com> Date: Wed, 3 Jun 2020 16:34:56 +0100 Subject: [PATCH 090/206] Add base64 encoding/decoding dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds base64 lib created by René Nyffenegger (with changes from Yannic Bonenberger). https://github.com/ReneNyffenegger/cpp-base64 This will be used to implement HTTP Basic Auth - to decode the Authorization header. --- .gitmodules | 3 +++ 3rdparty/cpp-base64 | 1 + cmake/cpp-base64-3rdparty-config.cmake | 8 ++++++++ 3 files changed, 12 insertions(+) create mode 160000 3rdparty/cpp-base64 create mode 100644 cmake/cpp-base64-3rdparty-config.cmake diff --git a/.gitmodules b/.gitmodules index ccfd018a..67740dc8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "civetweb"] path = 3rdparty/civetweb url = https://github.com/civetweb/civetweb.git +[submodule "3rdparty/cpp-base64"] + path = 3rdparty/cpp-base64 + url = https://github.com/ReneNyffenegger/cpp-base64.git diff --git a/3rdparty/cpp-base64 b/3rdparty/cpp-base64 new file mode 160000 index 00000000..b4c48f80 --- /dev/null +++ b/3rdparty/cpp-base64 @@ -0,0 +1 @@ +Subproject commit b4c48f80622e22c05aa721b2c1a87fa99c3814f3 diff --git a/cmake/cpp-base64-3rdparty-config.cmake b/cmake/cpp-base64-3rdparty-config.cmake new file mode 100644 index 00000000..ac35eaa9 --- /dev/null +++ b/cmake/cpp-base64-3rdparty-config.cmake @@ -0,0 +1,8 @@ +get_filename_component(_IMPORT_PREFIX "${PROJECT_SOURCE_DIR}/3rdparty/cpp-base64/" ABSOLUTE) + +add_library(base64 OBJECT + ${_IMPORT_PREFIX}/base64.h + ${_IMPORT_PREFIX}/base64.cpp + ) + +set(BASE64_INCLUDE_DIRS ${_IMPORT_PREFIX}) From 498c3c978c14426fb15fc376c835d5996cac395b Mon Sep 17 00:00:00 2001 From: James Harrison <00jamesh@gmail.com> Date: Thu, 4 Jun 2020 14:37:41 +0100 Subject: [PATCH 091/206] Add support for HTTP Basic Auth on scraping endpoints Adds a simple HTTP Basic Auth handler which can be registered to endpoints. This provides a mechanism for extracting user/password from the auth header; all further authentication logic is left to the user. --- pull/CMakeLists.txt | 6 ++ pull/include/prometheus/exposer.h | 6 ++ pull/src/basic_auth.cc | 75 ++++++++++++++++++++ pull/src/basic_auth.h | 39 ++++++++++ pull/src/endpoint.cc | 14 +++- pull/src/endpoint.h | 6 ++ pull/src/exposer.cc | 7 ++ pull/tests/integration/BUILD.bazel | 6 ++ pull/tests/integration/CMakeLists.txt | 9 +++ pull/tests/integration/sample_server_auth.cc | 42 +++++++++++ 10 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 pull/src/basic_auth.cc create mode 100644 pull/src/basic_auth.h create mode 100644 pull/tests/integration/sample_server_auth.cc diff --git a/pull/CMakeLists.txt b/pull/CMakeLists.txt index bfdf1351..aaf64d35 100644 --- a/pull/CMakeLists.txt +++ b/pull/CMakeLists.txt @@ -13,7 +13,11 @@ if(ENABLE_COMPRESSION) find_package(ZLIB REQUIRED) endif() +find_package(cpp-base64-3rdparty CONFIG REQUIRED) + add_library(pull + src/basic_auth.cc + src/basic_auth.h src/endpoint.cc src/endpoint.h src/exposer.cc @@ -21,6 +25,7 @@ add_library(pull src/handler.h src/metrics_collector.cc src/metrics_collector.h + $ ) add_library(${PROJECT_NAME}::pull ALIAS pull) @@ -40,6 +45,7 @@ target_include_directories(pull $ $ PRIVATE + ${BASE64_INCLUDE_DIRS} ${CIVETWEB_INCLUDE_DIRS} ) diff --git a/pull/include/prometheus/exposer.h b/pull/include/prometheus/exposer.h index f8122f01..1d7defce 100644 --- a/pull/include/prometheus/exposer.h +++ b/pull/include/prometheus/exposer.h @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -28,6 +29,11 @@ class PROMETHEUS_CPP_PULL_EXPORT Exposer { void RegisterCollectable(const std::weak_ptr& collectable, const std::string& uri = std::string("/metrics")); + void RegisterAuth( + std::function authCB, + const std::string& realm = "Prometheus-cpp Exporter", + const std::string& uri = std::string("/metrics")); + std::vector GetListeningPorts() const; private: diff --git a/pull/src/basic_auth.cc b/pull/src/basic_auth.cc new file mode 100644 index 00000000..5ad184a3 --- /dev/null +++ b/pull/src/basic_auth.cc @@ -0,0 +1,75 @@ +#include "basic_auth.h" + +#include + +#include "CivetServer.h" +#include "prometheus/detail/future_std.h" + +namespace prometheus { + +BasicAuthHandler::BasicAuthHandler(AuthFunc callback, std::string realm) + : callback_(std::move(callback)), realm_(std::move(realm)) {} + +bool BasicAuthHandler::authorize(CivetServer* server, mg_connection* conn) { + if (!AuthorizeInner(server, conn)) { + WriteUnauthorizedResponse(conn); + return false; + } + return true; +} + +bool BasicAuthHandler::AuthorizeInner(CivetServer* server, + mg_connection* conn) { + const char* authHeader = mg_get_header(conn, "Authorization"); + + if (authHeader == nullptr) { + // No auth header was provided. + return false; + } + std::string authHeaderStr = authHeader; + + // Basic auth header is expected to be of the form: + // "Basic dXNlcm5hbWU6cGFzc3dvcmQ=" + + const std::string prefix = "Basic "; + if (authHeaderStr.compare(0, prefix.size(), prefix) != 0) { + return false; + } + + // Strip the "Basic " prefix leaving the base64 encoded auth string + auto b64Auth = authHeaderStr.substr(prefix.size()); + + std::string decoded; + try { + decoded = base64_decode(b64Auth); + } catch (...) { + return false; + } + + // decoded auth string is expected to be of the form: + // "username:password" + // colons may not appear in the username. + auto splitPos = decoded.find(':'); + if (splitPos == std::string::npos) { + return false; + } + + auto username = decoded.substr(0, splitPos); + auto password = decoded.substr(splitPos + 1); + + // TODO: bool does not permit a distinction between 401 Unauthorized + // and 403 Forbidden. Authentication may succeed, but the user still + // not be authorized to perform the request. + return callback_(username, password); +} + +void BasicAuthHandler::WriteUnauthorizedResponse(mg_connection* conn) { + mg_printf(conn, "HTTP/1.1 401 Unauthorized\r\n"); + mg_printf(conn, "WWW-Authenticate: Basic realm=\"%s\"\r\n", realm_.c_str()); + mg_printf(conn, "Connection: close\r\n"); + mg_printf(conn, "Content-Length: 0\r\n"); + // end headers + mg_printf(conn, "\r\n"); +} + +} // namespace prometheus \ No newline at end of file diff --git a/pull/src/basic_auth.h b/pull/src/basic_auth.h new file mode 100644 index 00000000..c3121d60 --- /dev/null +++ b/pull/src/basic_auth.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include + +#include "CivetServer.h" +#include "prometheus/detail/pull_export.h" + +namespace prometheus { + +/** + * Handler for HTTP Basic authentication for Endpoints. + */ +class PROMETHEUS_CPP_PULL_EXPORT BasicAuthHandler : public CivetAuthHandler { + public: + using AuthFunc = std::function; + explicit BasicAuthHandler(AuthFunc callback, std::string realm); + + /** + * Implements civetweb authorization interface. + * + * Attempts to extract a username and password from the Authorization header + * to pass to the owning AuthHandler, `this->handler`. + * If handler returns true, permits the request to proceed. + * If handler returns false, or the Auth header is absent, + * rejects the request with 401 Unauthorized. + */ + bool authorize(CivetServer* server, mg_connection* conn) override; + + private: + bool AuthorizeInner(CivetServer* server, mg_connection* conn); + void WriteUnauthorizedResponse(mg_connection* conn); + + AuthFunc callback_; + std::string realm_; +}; + +} // namespace prometheus \ No newline at end of file diff --git a/pull/src/endpoint.cc b/pull/src/endpoint.cc index c4e7ebc7..cdbd0176 100644 --- a/pull/src/endpoint.cc +++ b/pull/src/endpoint.cc @@ -1,5 +1,6 @@ #include "endpoint.h" +#include "basic_auth.h" #include "handler.h" #include "prometheus/detail/future_std.h" @@ -16,13 +17,24 @@ Endpoint::Endpoint(CivetServer& server, std::string uri) server_.addHandler(uri_, metrics_handler_.get()); } -Endpoint::~Endpoint() { server_.removeHandler(uri_); } +Endpoint::~Endpoint() { + server_.removeHandler(uri_); + server_.removeAuthHandler(uri_); +} void Endpoint::RegisterCollectable( const std::weak_ptr& collectable) { collectables_.push_back(collectable); } +void Endpoint::RegisterAuth( + std::function authCB, + const std::string& realm) { + auth_handler_ = + detail::make_unique(std::move(authCB), realm); + server_.addAuthHandler(uri_, auth_handler_.get()); +} + const std::string& Endpoint::GetURI() const { return uri_; } } // namespace detail diff --git a/pull/src/endpoint.h b/pull/src/endpoint.h index 9b9c94bd..e2ad55f5 100644 --- a/pull/src/endpoint.h +++ b/pull/src/endpoint.h @@ -1,9 +1,11 @@ #pragma once +#include #include #include #include +#include "basic_auth.h" #include "prometheus/collectable.h" #include "prometheus/registry.h" @@ -19,6 +21,9 @@ class Endpoint { ~Endpoint(); void RegisterCollectable(const std::weak_ptr& collectable); + void RegisterAuth( + std::function authCB, + const std::string& realm); const std::string& GetURI() const; @@ -29,6 +34,7 @@ class Endpoint { // registry for "meta" metrics about the endpoint itself std::shared_ptr endpoint_registry_; std::unique_ptr metrics_handler_; + std::unique_ptr auth_handler_; }; } // namespace detail diff --git a/pull/src/exposer.cc b/pull/src/exposer.cc index a896b627..4326c349 100644 --- a/pull/src/exposer.cc +++ b/pull/src/exposer.cc @@ -28,6 +28,13 @@ void Exposer::RegisterCollectable(const std::weak_ptr& collectable, endpoint.RegisterCollectable(collectable); } +void Exposer::RegisterAuth( + std::function authCB, + const std::string& realm, const std::string& uri) { + auto& endpoint = GetEndpointForUri(uri); + endpoint.RegisterAuth(std::move(authCB), realm); +} + std::vector Exposer::GetListeningPorts() const { return server_->getListeningPorts(); } diff --git a/pull/tests/integration/BUILD.bazel b/pull/tests/integration/BUILD.bazel index 2e172af6..441dd25c 100644 --- a/pull/tests/integration/BUILD.bazel +++ b/pull/tests/integration/BUILD.bazel @@ -10,6 +10,12 @@ cc_binary( deps = ["//pull"], ) +cc_binary( + name = "sample-server_auth", + srcs = ["sample_server_auth.cc"], + deps = ["//pull"], +) + sh_test( name = "scrape-test", size = "small", diff --git a/pull/tests/integration/CMakeLists.txt b/pull/tests/integration/CMakeLists.txt index 82e41d08..74ed5bf1 100644 --- a/pull/tests/integration/CMakeLists.txt +++ b/pull/tests/integration/CMakeLists.txt @@ -16,3 +16,12 @@ target_link_libraries(sample_server_multi PRIVATE ${PROJECT_NAME}::pull ) + +add_executable(sample_server_auth + sample_server_auth.cc +) + +target_link_libraries(sample_server_auth + PRIVATE + ${PROJECT_NAME}::pull +) diff --git a/pull/tests/integration/sample_server_auth.cc b/pull/tests/integration/sample_server_auth.cc new file mode 100644 index 00000000..1248d55b --- /dev/null +++ b/pull/tests/integration/sample_server_auth.cc @@ -0,0 +1,42 @@ +#include +#include +#include + +#include +#include +#include + +int main() { + using namespace prometheus; + + // create an http server running on port 8080 + Exposer exposer{"127.0.0.1:8080", 1}; + + auto registry = std::make_shared(); + + // add a new counter family to the registry (families combine values with the + // same name, but distinct label dimensions) + auto& counter_family = BuildCounter() + .Name("time_running_seconds_total") + .Help("How many seconds is this server running?") + .Register(*registry); + + // add a counter to the metric family + auto& seconds_counter = counter_family.Add( + {{"another_label", "bar"}, {"yet_another_label", "baz"}}); + + // ask the exposer to scrape registry on incoming scrapes for "/metrics" + exposer.RegisterCollectable(registry, "/metrics"); + exposer.RegisterAuth( + [](const std::string& user, const std::string& password) { + return user == "test_user" && password == "test_password"; + }, + "Some Auth Realm"); + + for (;;) { + std::this_thread::sleep_for(std::chrono::seconds(1)); + // increment the counters by one (second) + seconds_counter.Increment(1.0); + } + return 0; +} From 4fc553e692390558495bb56c01e6154818fdee93 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 7 Jun 2020 11:52:32 +0200 Subject: [PATCH 092/206] Use header-only cppcodec lib and fix build Closes: #372 --- .github/scripts/run-prepare | 2 +- .github/scripts/run-prepare.cmd | 2 +- .gitmodules | 6 +++--- 3rdparty/cpp-base64 | 1 - 3rdparty/cppcodec | 1 + bazel/cppcodec.BUILD | 6 ++++++ bazel/repositories.bzl | 11 +++++++++++ cmake/Findcppcodec.cmake | 8 ++++++++ cmake/cpp-base64-3rdparty-config.cmake | 8 -------- cmake/cppcodec-3rdparty-config.cmake | 14 ++++++++++++++ pull/BUILD.bazel | 1 + pull/CMakeLists.txt | 13 +++++++++---- pull/src/basic_auth.cc | 11 ++++++----- pull/src/basic_auth.h | 2 +- 14 files changed, 62 insertions(+), 24 deletions(-) delete mode 160000 3rdparty/cpp-base64 create mode 160000 3rdparty/cppcodec create mode 100644 bazel/cppcodec.BUILD create mode 100644 cmake/Findcppcodec.cmake delete mode 100644 cmake/cpp-base64-3rdparty-config.cmake create mode 100644 cmake/cppcodec-3rdparty-config.cmake diff --git a/.github/scripts/run-prepare b/.github/scripts/run-prepare index 0fbe1045..5b5fafc9 100755 --- a/.github/scripts/run-prepare +++ b/.github/scripts/run-prepare @@ -34,6 +34,6 @@ esac case "${BUILDSYSTEM_ARG}" in cmake) - "${VCPKG_INSTALLATION_ROOT}/vcpkg" install benchmark civetweb curl gtest zlib + "${VCPKG_INSTALLATION_ROOT}/vcpkg" install benchmark civetweb cppcodec curl gtest zlib ;; esac diff --git a/.github/scripts/run-prepare.cmd b/.github/scripts/run-prepare.cmd index ec14d92f..0302a028 100644 --- a/.github/scripts/run-prepare.cmd +++ b/.github/scripts/run-prepare.cmd @@ -1,4 +1,4 @@ if [%1] == [cmake] ( - %VCPKG_INSTALLATION_ROOT%/vcpkg install benchmark civetweb curl gtest zlib || EXIT /B 1 + %VCPKG_INSTALLATION_ROOT%/vcpkg install benchmark civetweb cppcodec curl gtest zlib || EXIT /B 1 ) diff --git a/.gitmodules b/.gitmodules index 67740dc8..f7541b36 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,6 +4,6 @@ [submodule "civetweb"] path = 3rdparty/civetweb url = https://github.com/civetweb/civetweb.git -[submodule "3rdparty/cpp-base64"] - path = 3rdparty/cpp-base64 - url = https://github.com/ReneNyffenegger/cpp-base64.git +[submodule "3rdparty/cppcodec"] + path = 3rdparty/cppcodec + url = https://github.com/tplgy/cppcodec.git diff --git a/3rdparty/cpp-base64 b/3rdparty/cpp-base64 deleted file mode 160000 index b4c48f80..00000000 --- a/3rdparty/cpp-base64 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b4c48f80622e22c05aa721b2c1a87fa99c3814f3 diff --git a/3rdparty/cppcodec b/3rdparty/cppcodec new file mode 160000 index 00000000..302dc28f --- /dev/null +++ b/3rdparty/cppcodec @@ -0,0 +1 @@ +Subproject commit 302dc28f8fd5c8bf2ea8d7212aed3be884d5d166 diff --git a/bazel/cppcodec.BUILD b/bazel/cppcodec.BUILD new file mode 100644 index 00000000..ecde0e88 --- /dev/null +++ b/bazel/cppcodec.BUILD @@ -0,0 +1,6 @@ +cc_library( + name = "cppcodec", + hdrs = glob(["cppcodec/**/*.hpp"]), + includes = ["."], + visibility = ["//visibility:public"], +) diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index 005e3cf6..6195c614 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -45,6 +45,17 @@ def prometheus_cpp_repositories(): ], ) + maybe( + http_archive, + name = "com_github_tplgy_cppcodec", + sha256 = "0edaea2a9d9709d456aa99a1c3e17812ed130f9ef2b5c2d152c230a5cbc5c482", + strip_prefix = "cppcodec-0.2", + urls = [ + "https://github.com/tplgy/cppcodec/archive/v0.2.tar.gz", + ], + build_file = "@com_github_jupp0r_prometheus_cpp//bazel:cppcodec.BUILD", + ) + maybe( http_archive, name = "net_zlib_zlib", diff --git a/cmake/Findcppcodec.cmake b/cmake/Findcppcodec.cmake new file mode 100644 index 00000000..9c3e7b37 --- /dev/null +++ b/cmake/Findcppcodec.cmake @@ -0,0 +1,8 @@ +find_path(CPPCODEC_INCLUDE_DIR base64_rfc4648.hpp PATH_SUFFIXES include/cppcodec) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(cppcodec DEFAULT_MSG CPPCODEC_INCLUDE_DIR) + +if(cppcodec_FOUND) + set(CPPCODEC_INCLUDE_DIRS "${CPPCODEC_INCLUDE_DIR}") +endif() diff --git a/cmake/cpp-base64-3rdparty-config.cmake b/cmake/cpp-base64-3rdparty-config.cmake deleted file mode 100644 index ac35eaa9..00000000 --- a/cmake/cpp-base64-3rdparty-config.cmake +++ /dev/null @@ -1,8 +0,0 @@ -get_filename_component(_IMPORT_PREFIX "${PROJECT_SOURCE_DIR}/3rdparty/cpp-base64/" ABSOLUTE) - -add_library(base64 OBJECT - ${_IMPORT_PREFIX}/base64.h - ${_IMPORT_PREFIX}/base64.cpp - ) - -set(BASE64_INCLUDE_DIRS ${_IMPORT_PREFIX}) diff --git a/cmake/cppcodec-3rdparty-config.cmake b/cmake/cppcodec-3rdparty-config.cmake new file mode 100644 index 00000000..fd4be810 --- /dev/null +++ b/cmake/cppcodec-3rdparty-config.cmake @@ -0,0 +1,14 @@ +get_filename_component(_IMPORT_PREFIX "${PROJECT_SOURCE_DIR}/3rdparty/cppcodec/" ABSOLUTE) + +macro(set_and_check _var _file) + set(${_var} "${_file}") + if(NOT EXISTS "${_file}") + message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !") + endif() +endmacro() + +set_and_check(CPPCODEC_INCLUDE_DIR ${_IMPORT_PREFIX}) +set(CPPCODEC_INCLUDE_DIRS "${CPPCODEC_INCLUDE_DIR}") + +add_library(cppcodec INTERFACE) +target_include_directories(cppcodec INTERFACE "$") diff --git a/pull/BUILD.bazel b/pull/BUILD.bazel index 6d90c233..241df1b3 100644 --- a/pull/BUILD.bazel +++ b/pull/BUILD.bazel @@ -23,6 +23,7 @@ cc_library( deps = [ "//core", "@civetweb", + "@com_github_tplgy_cppcodec//:cppcodec", "@net_zlib_zlib//:z", ], ) diff --git a/pull/CMakeLists.txt b/pull/CMakeLists.txt index aaf64d35..800daeca 100644 --- a/pull/CMakeLists.txt +++ b/pull/CMakeLists.txt @@ -5,16 +5,21 @@ if(USE_THIRDPARTY_LIBRARIES) TARGETS civetweb EXPORT ${PROJECT_NAME}-targets ) + find_package(cppcodec-3rdparty CONFIG REQUIRED) + add_library(${PROJECT_NAME}::cppcodec ALIAS cppcodec) + install( + TARGETS cppcodec + EXPORT ${PROJECT_NAME}-targets + ) else() find_package(civetweb CONFIG REQUIRED) + find_package(cppcodec REQUIRED) endif() if(ENABLE_COMPRESSION) find_package(ZLIB REQUIRED) endif() -find_package(cpp-base64-3rdparty CONFIG REQUIRED) - add_library(pull src/basic_auth.cc src/basic_auth.h @@ -25,7 +30,6 @@ add_library(pull src/handler.h src/metrics_collector.cc src/metrics_collector.h - $ ) add_library(${PROJECT_NAME}::pull ALIAS pull) @@ -36,6 +40,7 @@ target_link_libraries(pull PRIVATE Threads::Threads $,${PROJECT_NAME}::civetweb,civetweb::civetweb-cpp> + $<$:${PROJECT_NAME}::cppcodec> $<$,$>>:rt> $<$:ZLIB::ZLIB> ) @@ -45,7 +50,7 @@ target_include_directories(pull $ $ PRIVATE - ${BASE64_INCLUDE_DIRS} + ${CPPCODEC_INCLUDE_DIRS} # needed as long as upstream cppcodec installs no config file with imported target ${CIVETWEB_INCLUDE_DIRS} ) diff --git a/pull/src/basic_auth.cc b/pull/src/basic_auth.cc index 5ad184a3..5e562b50 100644 --- a/pull/src/basic_auth.cc +++ b/pull/src/basic_auth.cc @@ -1,12 +1,14 @@ #include "basic_auth.h" -#include +#include #include "CivetServer.h" #include "prometheus/detail/future_std.h" namespace prometheus { +using base64 = cppcodec::base64_rfc4648; + BasicAuthHandler::BasicAuthHandler(AuthFunc callback, std::string realm) : callback_(std::move(callback)), realm_(std::move(realm)) {} @@ -18,8 +20,7 @@ bool BasicAuthHandler::authorize(CivetServer* server, mg_connection* conn) { return true; } -bool BasicAuthHandler::AuthorizeInner(CivetServer* server, - mg_connection* conn) { +bool BasicAuthHandler::AuthorizeInner(CivetServer*, mg_connection* conn) { const char* authHeader = mg_get_header(conn, "Authorization"); if (authHeader == nullptr) { @@ -41,7 +42,7 @@ bool BasicAuthHandler::AuthorizeInner(CivetServer* server, std::string decoded; try { - decoded = base64_decode(b64Auth); + decoded = base64::decode(b64Auth.data(), b64Auth.size()); } catch (...) { return false; } @@ -72,4 +73,4 @@ void BasicAuthHandler::WriteUnauthorizedResponse(mg_connection* conn) { mg_printf(conn, "\r\n"); } -} // namespace prometheus \ No newline at end of file +} // namespace prometheus diff --git a/pull/src/basic_auth.h b/pull/src/basic_auth.h index c3121d60..895f90ea 100644 --- a/pull/src/basic_auth.h +++ b/pull/src/basic_auth.h @@ -36,4 +36,4 @@ class PROMETHEUS_CPP_PULL_EXPORT BasicAuthHandler : public CivetAuthHandler { std::string realm_; }; -} // namespace prometheus \ No newline at end of file +} // namespace prometheus From d1f0eb18f8ad72eca0ab0605cd3f1a5e8fef8c5f Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Tue, 23 Jun 2020 11:39:05 +0200 Subject: [PATCH 093/206] chore(bazel): Use Google Benchmark 1.5.1 --- bazel/repositories.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index 6195c614..02838751 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -38,10 +38,10 @@ def prometheus_cpp_repositories(): maybe( http_archive, name = "com_github_google_benchmark", - sha256 = "3c6a165b6ecc948967a1ead710d4a181d7b0fbcaa183ef7ea84604994966221a", - strip_prefix = "benchmark-1.5.0", + sha256 = "23082937d1663a53b90cb5b61df4bcc312f6dee7018da78ba00dd6bd669dfef2", + strip_prefix = "benchmark-1.5.1", urls = [ - "https://github.com/google/benchmark/archive/v1.5.0.tar.gz", + "https://github.com/google/benchmark/archive/v1.5.1.tar.gz", ], ) From 2501c04f80d04167ef2b4eb9b7c3ae6047a5846b Mon Sep 17 00:00:00 2001 From: Michael Mlsna Date: Thu, 10 Sep 2020 17:36:32 -0500 Subject: [PATCH 094/206] Avoid race when registering a collectable A thread registering a `Collectable` with the `Exposer` may end up invalidating iterators to the `collectables_` vector inside `Endpoint` while a `CivetServer` handler thread is iterating the vector. Move the `collectables_` vector to `MetricsHandler` where all accesses can be guarded by a mutex. --- pull/src/endpoint.cc | 6 +++--- pull/src/endpoint.h | 1 - pull/src/handler.cc | 20 ++++++++++++++------ pull/src/handler.h | 9 ++++++--- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/pull/src/endpoint.cc b/pull/src/endpoint.cc index cdbd0176..274e17c5 100644 --- a/pull/src/endpoint.cc +++ b/pull/src/endpoint.cc @@ -11,8 +11,8 @@ Endpoint::Endpoint(CivetServer& server, std::string uri) : server_(server), uri_(std::move(uri)), endpoint_registry_(std::make_shared()), - metrics_handler_(detail::make_unique( - collectables_, *endpoint_registry_)) { + metrics_handler_( + detail::make_unique(*endpoint_registry_)) { RegisterCollectable(endpoint_registry_); server_.addHandler(uri_, metrics_handler_.get()); } @@ -24,7 +24,7 @@ Endpoint::~Endpoint() { void Endpoint::RegisterCollectable( const std::weak_ptr& collectable) { - collectables_.push_back(collectable); + metrics_handler_->RegisterCollectable(collectable); } void Endpoint::RegisterAuth( diff --git a/pull/src/endpoint.h b/pull/src/endpoint.h index e2ad55f5..af64d5f8 100644 --- a/pull/src/endpoint.h +++ b/pull/src/endpoint.h @@ -30,7 +30,6 @@ class Endpoint { private: CivetServer& server_; const std::string uri_; - std::vector> collectables_; // registry for "meta" metrics about the endpoint itself std::shared_ptr endpoint_registry_; std::unique_ptr metrics_handler_; diff --git a/pull/src/handler.cc b/pull/src/handler.cc index eaad7420..69e6d9d1 100644 --- a/pull/src/handler.cc +++ b/pull/src/handler.cc @@ -16,11 +16,8 @@ namespace prometheus { namespace detail { -MetricsHandler::MetricsHandler( - const std::vector>& collectables, - Registry& registry) - : collectables_(collectables), - bytes_transferred_family_( +MetricsHandler::MetricsHandler(Registry& registry) + : bytes_transferred_family_( BuildCounter() .Name("exposer_transferred_bytes_total") .Help("Transferred bytes to metrics services") @@ -116,10 +113,21 @@ static std::size_t WriteResponse(struct mg_connection* conn, return body.size(); } +void MetricsHandler::RegisterCollectable( + const std::weak_ptr& collectable) { + std::lock_guard lock{collectables_mutex_}; + collectables_.push_back(collectable); +} + bool MetricsHandler::handleGet(CivetServer*, struct mg_connection* conn) { auto start_time_of_request = std::chrono::steady_clock::now(); - auto metrics = CollectMetrics(collectables_); + std::vector metrics; + + { + std::lock_guard lock{collectables_mutex_}; + metrics = CollectMetrics(collectables_); + } auto serializer = std::unique_ptr{new TextSerializer()}; diff --git a/pull/src/handler.h b/pull/src/handler.h index f28f7f57..79ddc4a9 100644 --- a/pull/src/handler.h +++ b/pull/src/handler.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include "CivetServer.h" @@ -12,13 +13,15 @@ namespace prometheus { namespace detail { class MetricsHandler : public CivetHandler { public: - MetricsHandler(const std::vector>& collectables, - Registry& registry); + explicit MetricsHandler(Registry& registry); + + void RegisterCollectable(const std::weak_ptr& collectable); bool handleGet(CivetServer* server, struct mg_connection* conn) override; private: - const std::vector>& collectables_; + std::mutex collectables_mutex_; + std::vector> collectables_; Family& bytes_transferred_family_; Counter& bytes_transferred_; Family& num_scrapes_family_; From cfe7f643492205de7529b96ad3a05dae4e6921a3 Mon Sep 17 00:00:00 2001 From: technicianted Date: Fri, 18 Sep 2020 16:34:24 -0700 Subject: [PATCH 095/206] Reuse curl handle --- push/include/prometheus/gateway.h | 7 +++- push/src/gateway.cc | 55 +++++++++++++++++-------------- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/push/include/prometheus/gateway.h b/push/include/prometheus/gateway.h index 5d48cba8..1704e049 100644 --- a/push/include/prometheus/gateway.h +++ b/push/include/prometheus/gateway.h @@ -6,10 +6,13 @@ #include #include #include +#include #include "prometheus/detail/push_export.h" #include "prometheus/registry.h" +#include + namespace prometheus { class PROMETHEUS_CPP_PUSH_EXPORT Gateway { @@ -46,6 +49,8 @@ class PROMETHEUS_CPP_PUSH_EXPORT Gateway { std::string jobUri_; std::string labels_; std::string auth_; + CURL *curl_; + std::mutex curlMutex_; using CollectableEntry = std::pair, std::string>; std::vector collectables_; @@ -59,7 +64,7 @@ class PROMETHEUS_CPP_PUSH_EXPORT Gateway { }; int performHttpRequest(HttpMethod method, const std::string& uri, - const std::string& body) const; + const std::string& body); int push(HttpMethod method); diff --git a/push/src/gateway.cc b/push/src/gateway.cc index d23e8e3c..3945bc50 100644 --- a/push/src/gateway.cc +++ b/push/src/gateway.cc @@ -8,8 +8,6 @@ #include "prometheus/serializer.h" #include "prometheus/text_serializer.h" -#include - namespace prometheus { static const char CONTENT_TYPE[] = @@ -34,9 +32,16 @@ Gateway::Gateway(const std::string host, const std::string port, labelStream << "/" << label.first << "/" << label.second; } labels_ = labelStream.str(); + curl_ = nullptr; } -Gateway::~Gateway() { curl_global_cleanup(); } +Gateway::~Gateway() { + std::lock_guard l(curlMutex_); + if (curl_) { + curl_easy_cleanup(curl_); + } + curl_global_cleanup(); +} const Gateway::Labels Gateway::GetInstanceLabel(std::string hostname) { if (hostname.empty()) { @@ -59,53 +64,55 @@ void Gateway::RegisterCollectable(const std::weak_ptr& collectable, } int Gateway::performHttpRequest(HttpMethod method, const std::string& uri, - const std::string& body) const { - auto curl = curl_easy_init(); - if (!curl) { - return -CURLE_FAILED_INIT; + const std::string& body) { + std::lock_guard l(curlMutex_); + if (!curl_) { + curl_ = curl_easy_init(); + if (!curl_) { + return -CURLE_FAILED_INIT; + } } - - curl_easy_setopt(curl, CURLOPT_URL, uri.c_str()); + curl_easy_reset(curl_); + curl_easy_setopt(curl_, CURLOPT_URL, uri.c_str()); curl_slist* header_chunk = nullptr; if (!body.empty()) { header_chunk = curl_slist_append(nullptr, CONTENT_TYPE); - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_chunk); + curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, header_chunk); - curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.size()); - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.data()); + curl_easy_setopt(curl_, CURLOPT_POSTFIELDSIZE, body.size()); + curl_easy_setopt(curl_, CURLOPT_POSTFIELDS, body.data()); } if (!auth_.empty()) { - curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); - curl_easy_setopt(curl, CURLOPT_USERPWD, auth_.c_str()); + curl_easy_setopt(curl_, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + curl_easy_setopt(curl_, CURLOPT_USERPWD, auth_.c_str()); } switch (method) { case HttpMethod::Post: - curl_easy_setopt(curl, CURLOPT_HTTPGET, 0L); - curl_easy_setopt(curl, CURLOPT_NOBODY, 0L); + curl_easy_setopt(curl_, CURLOPT_HTTPGET, 0L); + curl_easy_setopt(curl_, CURLOPT_NOBODY, 0L); break; case HttpMethod::Put: - curl_easy_setopt(curl, CURLOPT_NOBODY, 0L); - curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); + curl_easy_setopt(curl_, CURLOPT_NOBODY, 0L); + curl_easy_setopt(curl_, CURLOPT_CUSTOMREQUEST, "PUT"); break; case HttpMethod::Delete: - curl_easy_setopt(curl, CURLOPT_HTTPGET, 0L); - curl_easy_setopt(curl, CURLOPT_NOBODY, 0L); - curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE"); + curl_easy_setopt(curl_, CURLOPT_HTTPGET, 0L); + curl_easy_setopt(curl_, CURLOPT_NOBODY, 0L); + curl_easy_setopt(curl_, CURLOPT_CUSTOMREQUEST, "DELETE"); break; } - auto curl_error = curl_easy_perform(curl); + auto curl_error = curl_easy_perform(curl_); long response_code; - curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_getinfo(curl_, CURLINFO_RESPONSE_CODE, &response_code); - curl_easy_cleanup(curl); curl_slist_free_all(header_chunk); if (curl_error != CURLE_OK) { From acb900339e30d249b83831edd93010159832214d Mon Sep 17 00:00:00 2001 From: technicianted Date: Fri, 18 Sep 2020 18:21:39 -0700 Subject: [PATCH 096/206] Use indirection to avoid curl include --- push/include/prometheus/gateway.h | 8 ++- push/src/gateway.cc | 81 +++++++++++++++++++------------ 2 files changed, 54 insertions(+), 35 deletions(-) diff --git a/push/include/prometheus/gateway.h b/push/include/prometheus/gateway.h index 1704e049..c60a027f 100644 --- a/push/include/prometheus/gateway.h +++ b/push/include/prometheus/gateway.h @@ -6,15 +6,14 @@ #include #include #include -#include #include "prometheus/detail/push_export.h" #include "prometheus/registry.h" -#include - namespace prometheus { +class CurlWrapper; + class PROMETHEUS_CPP_PUSH_EXPORT Gateway { public: using Labels = std::map; @@ -49,8 +48,7 @@ class PROMETHEUS_CPP_PUSH_EXPORT Gateway { std::string jobUri_; std::string labels_; std::string auth_; - CURL *curl_; - std::mutex curlMutex_; + std::unique_ptr curlWrapper_; using CollectableEntry = std::pair, std::string>; std::vector collectables_; diff --git a/push/src/gateway.cc b/push/src/gateway.cc index 3945bc50..4962a70b 100644 --- a/push/src/gateway.cc +++ b/push/src/gateway.cc @@ -3,16 +3,44 @@ #include #include +#include #include "prometheus/client_metric.h" #include "prometheus/serializer.h" #include "prometheus/text_serializer.h" +#include + namespace prometheus { static const char CONTENT_TYPE[] = "Content-Type: text/plain; version=0.0.4; charset=utf-8"; +class CurlWrapper { +public: + CurlWrapper() { + curl_ = nullptr; + } + ~CurlWrapper() { + std::lock_guard l(mutex_); + if (curl_) { + curl_easy_cleanup(curl_); + } + } + + CURL *curl() { + std::lock_guard l(mutex_); + if (!curl_) { + curl_ = curl_easy_init(); + } + return curl_; + } + +private: + CURL *curl_; + std::mutex mutex_; +}; + Gateway::Gateway(const std::string host, const std::string port, const std::string jobname, const Labels& labels, const std::string username, const std::string password) { @@ -32,16 +60,10 @@ Gateway::Gateway(const std::string host, const std::string port, labelStream << "/" << label.first << "/" << label.second; } labels_ = labelStream.str(); - curl_ = nullptr; + curlWrapper_ = std::move(std::unique_ptr(new CurlWrapper())); } -Gateway::~Gateway() { - std::lock_guard l(curlMutex_); - if (curl_) { - curl_easy_cleanup(curl_); - } - curl_global_cleanup(); -} +Gateway::~Gateway() { curl_global_cleanup(); } const Gateway::Labels Gateway::GetInstanceLabel(std::string hostname) { if (hostname.empty()) { @@ -65,53 +87,52 @@ void Gateway::RegisterCollectable(const std::weak_ptr& collectable, int Gateway::performHttpRequest(HttpMethod method, const std::string& uri, const std::string& body) { - std::lock_guard l(curlMutex_); - if (!curl_) { - curl_ = curl_easy_init(); - if (!curl_) { - return -CURLE_FAILED_INIT; - } + + auto curl = curlWrapper_->curl(); + if (!curl) { + return -CURLE_FAILED_INIT; } - curl_easy_reset(curl_); - curl_easy_setopt(curl_, CURLOPT_URL, uri.c_str()); + + curl_easy_reset(curl); + curl_easy_setopt(curl, CURLOPT_URL, uri.c_str()); curl_slist* header_chunk = nullptr; if (!body.empty()) { header_chunk = curl_slist_append(nullptr, CONTENT_TYPE); - curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, header_chunk); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_chunk); - curl_easy_setopt(curl_, CURLOPT_POSTFIELDSIZE, body.size()); - curl_easy_setopt(curl_, CURLOPT_POSTFIELDS, body.data()); + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.size()); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.data()); } if (!auth_.empty()) { - curl_easy_setopt(curl_, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); - curl_easy_setopt(curl_, CURLOPT_USERPWD, auth_.c_str()); + curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + curl_easy_setopt(curl, CURLOPT_USERPWD, auth_.c_str()); } switch (method) { case HttpMethod::Post: - curl_easy_setopt(curl_, CURLOPT_HTTPGET, 0L); - curl_easy_setopt(curl_, CURLOPT_NOBODY, 0L); + curl_easy_setopt(curl, CURLOPT_HTTPGET, 0L); + curl_easy_setopt(curl, CURLOPT_NOBODY, 0L); break; case HttpMethod::Put: - curl_easy_setopt(curl_, CURLOPT_NOBODY, 0L); - curl_easy_setopt(curl_, CURLOPT_CUSTOMREQUEST, "PUT"); + curl_easy_setopt(curl, CURLOPT_NOBODY, 0L); + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); break; case HttpMethod::Delete: - curl_easy_setopt(curl_, CURLOPT_HTTPGET, 0L); - curl_easy_setopt(curl_, CURLOPT_NOBODY, 0L); - curl_easy_setopt(curl_, CURLOPT_CUSTOMREQUEST, "DELETE"); + curl_easy_setopt(curl, CURLOPT_HTTPGET, 0L); + curl_easy_setopt(curl, CURLOPT_NOBODY, 0L); + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE"); break; } - auto curl_error = curl_easy_perform(curl_); + auto curl_error = curl_easy_perform(curl); long response_code; - curl_easy_getinfo(curl_, CURLINFO_RESPONSE_CODE, &response_code); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); curl_slist_free_all(header_chunk); From 086629726de1401fdb0a8fc9ced54ec18ace34aa Mon Sep 17 00:00:00 2001 From: Jupp Mueller Date: Wed, 23 Sep 2020 00:45:57 -0700 Subject: [PATCH 097/206] Fix coverage from forks (#391) * Fix coverage from forks Understandably, pull requests originating in forks won't get access to secrets in github (in order to prevent them being extracted). This change makes coverage upload only run from PRs or pushes originating in this repo, getting rid of failures for external contributors. * Fix syntax error in workflows Co-authored-by: Gregor Jasny * Fix syntax again Co-authored-by: Gregor Jasny --- .github/workflows/coverage.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 094218e4..53c8f88b 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -20,6 +20,7 @@ jobs: - name: Prepare run: .github/scripts/run-prepare ${{ matrix.buildsystem }} ${{ matrix.os }} - name: Test + if: github.repository == 'jupp0r/prometheus-cpp' env: COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} COVERALLS_GIT_BRANCH: "${{ github.ref }}" From 7175a1bfa0b5ce8936c9c3e0d3bea98e9bc24b7b Mon Sep 17 00:00:00 2001 From: technicianted Date: Thu, 24 Sep 2020 17:50:09 -0700 Subject: [PATCH 098/206] Use mutex to protect http operation --- push/include/prometheus/gateway.h | 1 + push/src/gateway.cc | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/push/include/prometheus/gateway.h b/push/include/prometheus/gateway.h index c60a027f..a7a6e1d9 100644 --- a/push/include/prometheus/gateway.h +++ b/push/include/prometheus/gateway.h @@ -49,6 +49,7 @@ class PROMETHEUS_CPP_PUSH_EXPORT Gateway { std::string labels_; std::string auth_; std::unique_ptr curlWrapper_; + std::mutex mutex_; using CollectableEntry = std::pair, std::string>; std::vector collectables_; diff --git a/push/src/gateway.cc b/push/src/gateway.cc index 4962a70b..635d1d31 100644 --- a/push/src/gateway.cc +++ b/push/src/gateway.cc @@ -22,14 +22,12 @@ class CurlWrapper { curl_ = nullptr; } ~CurlWrapper() { - std::lock_guard l(mutex_); if (curl_) { curl_easy_cleanup(curl_); } } CURL *curl() { - std::lock_guard l(mutex_); if (!curl_) { curl_ = curl_easy_init(); } @@ -38,7 +36,6 @@ class CurlWrapper { private: CURL *curl_; - std::mutex mutex_; }; Gateway::Gateway(const std::string host, const std::string port, @@ -87,7 +84,8 @@ void Gateway::RegisterCollectable(const std::weak_ptr& collectable, int Gateway::performHttpRequest(HttpMethod method, const std::string& uri, const std::string& body) { - + std::lock_guard l(mutex_); + auto curl = curlWrapper_->curl(); if (!curl) { return -CURLE_FAILED_INIT; From 33344cd0e0c9aa7e6cce4b0d1232be1005197b7a Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 27 Sep 2020 17:08:32 +0200 Subject: [PATCH 099/206] ci: require fixed bazel version bazelisk has a bug when retrieving the bazle version from GCS due to github rate limiting. See https://github.com/bazelbuild/bazelisk/issues/170 Until we export our GITHUB_TOKEN or bazelisk is fixed we pin the bazel version to 3.5.0 (to avoid unreleased 3.5.1). --- .bazelversion | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bazelversion diff --git a/.bazelversion b/.bazelversion new file mode 100644 index 00000000..1545d966 --- /dev/null +++ b/.bazelversion @@ -0,0 +1 @@ +3.5.0 From d0e1056016d4ef1c91317f01e7cce1cb82eb1198 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 27 Sep 2020 15:32:41 +0100 Subject: [PATCH 100/206] core: Explicitly link against libatomic when needed Closes: #394 --- CMakeLists.txt | 4 ++++ cmake/CheckAtomic.cmake | 37 +++++++++++++++++++++++++++++++ core/CMakeLists.txt | 6 +++++ pull/include/prometheus/exposer.h | 1 - 4 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 cmake/CheckAtomic.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 79a10aea..a7e30873 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,10 @@ endif() set(CMAKE_THREAD_PREFER_PTHREAD TRUE) find_package(Threads) +# check for required libatomic + +include(CheckAtomic) + if(ENABLE_TESTING) if(USE_THIRDPARTY_LIBRARIES) find_package(googlemock-3rdparty CONFIG REQUIRED) diff --git a/cmake/CheckAtomic.cmake b/cmake/CheckAtomic.cmake new file mode 100644 index 00000000..386cb2c3 --- /dev/null +++ b/cmake/CheckAtomic.cmake @@ -0,0 +1,37 @@ +# Inspired by CheckAtomic.cmake from LLVM project: +# https://github.com/llvm/llvm-project/blob/master/llvm/cmake/modules/CheckAtomic.cmake +# +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +include(CheckCXXSourceCompiles) +include(CheckLibraryExists) + +function(check_working_cxx_atomics varname) + check_cxx_source_compiles(" +#include +#include +std::atomic x(0); +int main() { + std::uint64_t i = x.load(std::memory_order_relaxed); + return 0; +} +" ${varname}) +endfunction() + +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") + # First check if atomics work without the library. + check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB) + # If not, check if the library exists, and atomics work with it. + if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB) + check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMIC) + if(HAVE_CXX_LIBATOMIC) + list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") + check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB) + if(NOT HAVE_CXX_ATOMICS_WITH_LIB) + message(FATAL_ERROR "Host compiler must support 64-bit std::atomic!") + endif() + else() + message(FATAL_ERROR "Host compiler appears to require libatomic for 64-bit operations, but cannot find it.") + endif() + endif() +endif() diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index dad457e7..11096a0b 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -23,6 +23,12 @@ target_link_libraries(core $<$,$>>:rt> ) +if(HAVE_CXX_LIBATOMIC) + # the exported library config must use libatomic unconditionally + # (the HAVE_CXX_LIBATOMIC variable should not leak into the target config) + target_link_libraries(core PUBLIC atomic) +endif() + target_include_directories(core PUBLIC $ diff --git a/pull/include/prometheus/exposer.h b/pull/include/prometheus/exposer.h index 1d7defce..1f3b0775 100644 --- a/pull/include/prometheus/exposer.h +++ b/pull/include/prometheus/exposer.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include From 823b40628d92283a5e65ffcf8f465922b6cbba96 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 27 Sep 2020 17:57:40 +0200 Subject: [PATCH 101/206] formatting --- push/src/gateway.cc | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/push/src/gateway.cc b/push/src/gateway.cc index 635d1d31..543fa4b0 100644 --- a/push/src/gateway.cc +++ b/push/src/gateway.cc @@ -1,41 +1,39 @@ #include "prometheus/gateway.h" +#include + #include -#include #include +#include #include "prometheus/client_metric.h" #include "prometheus/serializer.h" #include "prometheus/text_serializer.h" -#include - namespace prometheus { static const char CONTENT_TYPE[] = "Content-Type: text/plain; version=0.0.4; charset=utf-8"; class CurlWrapper { -public: - CurlWrapper() { - curl_ = nullptr; - } + public: + CurlWrapper() { curl_ = nullptr; } ~CurlWrapper() { if (curl_) { curl_easy_cleanup(curl_); } } - CURL *curl() { + CURL* curl() { if (!curl_) { curl_ = curl_easy_init(); } return curl_; } -private: - CURL *curl_; + private: + CURL* curl_; }; Gateway::Gateway(const std::string host, const std::string port, @@ -85,7 +83,7 @@ void Gateway::RegisterCollectable(const std::weak_ptr& collectable, int Gateway::performHttpRequest(HttpMethod method, const std::string& uri, const std::string& body) { std::lock_guard l(mutex_); - + auto curl = curlWrapper_->curl(); if (!curl) { return -CURLE_FAILED_INIT; From 9012fab11561e8d9f52af884c6d06587e4754c88 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 27 Sep 2020 18:04:35 +0200 Subject: [PATCH 102/206] push: slightly refactor gateway --- push/src/gateway.cc | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/push/src/gateway.cc b/push/src/gateway.cc index 543fa4b0..d672a331 100644 --- a/push/src/gateway.cc +++ b/push/src/gateway.cc @@ -8,6 +8,7 @@ #include #include "prometheus/client_metric.h" +#include "prometheus/detail/future_std.h" #include "prometheus/serializer.h" #include "prometheus/text_serializer.h" @@ -18,12 +19,7 @@ static const char CONTENT_TYPE[] = class CurlWrapper { public: - CurlWrapper() { curl_ = nullptr; } - ~CurlWrapper() { - if (curl_) { - curl_easy_cleanup(curl_); - } - } + ~CurlWrapper() { curl_easy_cleanup(curl_); } CURL* curl() { if (!curl_) { @@ -33,7 +29,7 @@ class CurlWrapper { } private: - CURL* curl_; + CURL* curl_ = nullptr; }; Gateway::Gateway(const std::string host, const std::string port, @@ -41,6 +37,7 @@ Gateway::Gateway(const std::string host, const std::string port, const std::string username, const std::string password) { /* In windows, this will init the winsock stuff */ curl_global_init(CURL_GLOBAL_ALL); + curlWrapper_ = detail::make_unique(); std::stringstream jobUriStream; jobUriStream << host << ':' << port << "/metrics/job/" << jobname; @@ -55,7 +52,6 @@ Gateway::Gateway(const std::string host, const std::string port, labelStream << "/" << label.first << "/" << label.second; } labels_ = labelStream.str(); - curlWrapper_ = std::move(std::unique_ptr(new CurlWrapper())); } Gateway::~Gateway() { curl_global_cleanup(); } @@ -95,7 +91,7 @@ int Gateway::performHttpRequest(HttpMethod method, const std::string& uri, curl_slist* header_chunk = nullptr; if (!body.empty()) { - header_chunk = curl_slist_append(nullptr, CONTENT_TYPE); + header_chunk = curl_slist_append(header_chunk, CONTENT_TYPE); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_chunk); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.size()); From bf7b75510788bca962c99790b97a3c4325e6d654 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 1 Oct 2020 08:42:35 +0200 Subject: [PATCH 103/206] chore: Use google-benchmark 1.5.2 --- bazel/repositories.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index 02838751..6a7f3c9f 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -38,10 +38,10 @@ def prometheus_cpp_repositories(): maybe( http_archive, name = "com_github_google_benchmark", - sha256 = "23082937d1663a53b90cb5b61df4bcc312f6dee7018da78ba00dd6bd669dfef2", - strip_prefix = "benchmark-1.5.1", + sha256 = "dccbdab796baa1043f04982147e67bb6e118fe610da2c65f88912d73987e700c", + strip_prefix = "benchmark-1.5.2", urls = [ - "https://github.com/google/benchmark/archive/v1.5.1.tar.gz", + "https://github.com/google/benchmark/archive/v1.5.2.tar.gz", ], ) From 0a912f72f2c6010828b048688140d6a34dcb64c8 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 1 Oct 2020 08:44:33 +0200 Subject: [PATCH 104/206] chore: Use curl 1.72.0 --- bazel/repositories.bzl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index 6a7f3c9f..ac7dd79c 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -26,11 +26,11 @@ def prometheus_cpp_repositories(): maybe( http_archive, name = "com_github_curl", - sha256 = "01ae0c123dee45b01bbaef94c0bc00ed2aec89cb2ee0fd598e0d302a6b5e0a98", - strip_prefix = "curl-7.69.1", + sha256 = "d4d5899a3868fbb6ae1856c3e55a32ce35913de3956d1973caccd37bd0174fa2", + strip_prefix = "curl-7.72.0", urls = [ - "https://github.com/curl/curl/releases/download/curl-7_69_1/curl-7.69.1.tar.gz", - "https://curl.haxx.se/download/curl-7.69.1.tar.gz", + "https://github.com/curl/curl/releases/download/curl-7_72_0/curl-7.72.0.tar.gz", + "https://curl.haxx.se/download/curl-7.72.0.tar.gz", ], build_file = "@com_github_jupp0r_prometheus_cpp//bazel:curl.BUILD", ) From 6e336ec66d1a0c4f52a3ae7a52a49ff5dbc917ef Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 1 Oct 2020 08:37:20 +0200 Subject: [PATCH 105/206] chore: Use civetweb 1.13 --- 3rdparty/civetweb | 2 +- bazel/civetweb.BUILD | 1 + bazel/repositories.bzl | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/3rdparty/civetweb b/3rdparty/civetweb index 4b440a33..8e243456 160000 --- a/3rdparty/civetweb +++ b/3rdparty/civetweb @@ -1 +1 @@ -Subproject commit 4b440a339979852d5a51fb11a822952712231c23 +Subproject commit 8e243456965c9be5212cb96519da69cd54550e3d diff --git a/bazel/civetweb.BUILD b/bazel/civetweb.BUILD index e8d60241..52ef9130 100644 --- a/bazel/civetweb.BUILD +++ b/bazel/civetweb.BUILD @@ -23,6 +23,7 @@ cc_library( name = "libcivetweb", srcs = [ "src/civetweb.c", + "src/response.inl", ], hdrs = [ "include/civetweb.h", diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index ac7dd79c..c8669b28 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -5,10 +5,10 @@ def prometheus_cpp_repositories(): maybe( http_archive, name = "civetweb", - strip_prefix = "civetweb-1.12", - sha256 = "8cab1e2ad8fb3e2e81fed0b2321a5afbd7269a644c44ed4c3607e0a212c6d9e1", + strip_prefix = "civetweb-1.13", + sha256 = "a7ccc76c2f1b5f4e8d855eb328ed542f8fe3b882a6da868781799a98f4acdedc", urls = [ - "https://github.com/civetweb/civetweb/archive/v1.12.tar.gz", + "https://github.com/civetweb/civetweb/archive/v1.13.tar.gz", ], build_file = "@com_github_jupp0r_prometheus_cpp//bazel:civetweb.BUILD", ) From fc7870b060a4b97c8c19cee8dfc5dbf58edf7977 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 1 Oct 2020 09:04:59 +0200 Subject: [PATCH 106/206] chore: Use Bazel 3.5.1 Bazelisk has been fixed but we need to wait a little bit until the fixed version lands on the GitHub Action workers. --- .bazelversion | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bazelversion b/.bazelversion index 1545d966..d5c0c991 100644 --- a/.bazelversion +++ b/.bazelversion @@ -1 +1 @@ -3.5.0 +3.5.1 From 62897f9e794e9f16471e8a53f367268109e7fa6e Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 1 Oct 2020 09:06:47 +0200 Subject: [PATCH 107/206] chore: Raise version to v0.10.0 due to changed public interface --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a7e30873..0f66577e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.12 FATAL_ERROR) -project(prometheus-cpp VERSION 0.9.0) +project(prometheus-cpp VERSION 0.10.0) include(GenerateExportHeader) include(GNUInstallDirs) From bf9d2e1759bcf62e8a0204296737c4c014971067 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Fri, 2 Oct 2020 08:46:18 +0200 Subject: [PATCH 108/206] fix(cmake): Fix warning in CheckAtomic --- cmake/CheckAtomic.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/CheckAtomic.cmake b/cmake/CheckAtomic.cmake index 386cb2c3..bbb6e474 100644 --- a/cmake/CheckAtomic.cmake +++ b/cmake/CheckAtomic.cmake @@ -13,7 +13,7 @@ function(check_working_cxx_atomics varname) std::atomic x(0); int main() { std::uint64_t i = x.load(std::memory_order_relaxed); - return 0; + return static_cast(i); } " ${varname}) endfunction() From 9aae240e236171ae7a04cfaba0fe99c2da76f4ac Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 17 Oct 2020 17:55:03 +0200 Subject: [PATCH 109/206] ci: use latest bazel --- .bazelversion | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .bazelversion diff --git a/.bazelversion b/.bazelversion deleted file mode 100644 index d5c0c991..00000000 --- a/.bazelversion +++ /dev/null @@ -1 +0,0 @@ -3.5.1 From cd0ba085d511d13e8a53066f923702902de7d5a5 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 17 Oct 2020 18:11:43 +0200 Subject: [PATCH 110/206] push: use curl 7.73.0 --- bazel/repositories.bzl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index c8669b28..1d92596c 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -26,11 +26,11 @@ def prometheus_cpp_repositories(): maybe( http_archive, name = "com_github_curl", - sha256 = "d4d5899a3868fbb6ae1856c3e55a32ce35913de3956d1973caccd37bd0174fa2", - strip_prefix = "curl-7.72.0", + sha256 = "ba98332752257b47b9dea6d8c0ad25ec1745c20424f1dd3ff2c99ab59e97cf91", + strip_prefix = "curl-7.73.0", urls = [ - "https://github.com/curl/curl/releases/download/curl-7_72_0/curl-7.72.0.tar.gz", - "https://curl.haxx.se/download/curl-7.72.0.tar.gz", + "https://github.com/curl/curl/releases/download/curl-7_73_0/curl-7.73.0.tar.gz", + "https://curl.haxx.se/download/curl-7.73.0.tar.gz", ], build_file = "@com_github_jupp0r_prometheus_cpp//bazel:curl.BUILD", ) From f42e9b9c7a894154597a21373a38f9f3413ce388 Mon Sep 17 00:00:00 2001 From: David Lenfesty Date: Wed, 21 Oct 2020 16:18:09 -0600 Subject: [PATCH 111/206] packaging: Add shlib generation. Produces a more correct debian package. --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f66577e..96056e04 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -129,6 +129,7 @@ if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}") endif() + set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON) set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) From 054b49ba4a0c6066ea7c222008cf56baf56b0372 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 1 Nov 2020 12:09:05 +0100 Subject: [PATCH 112/206] core: allow logically negative gauge increments and decrements This is in-line with the golang prometheus client library. --- core/src/counter.cc | 7 ++++++- core/src/gauge.cc | 6 ------ core/tests/gauge_test.cc | 8 +++----- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/core/src/counter.cc b/core/src/counter.cc index fc5b6f30..2a934635 100644 --- a/core/src/counter.cc +++ b/core/src/counter.cc @@ -4,7 +4,12 @@ namespace prometheus { void Counter::Increment() { gauge_.Increment(); } -void Counter::Increment(const double val) { gauge_.Increment(val); } +void Counter::Increment(const double val) { + if (val < 0.0) { + return; + } + gauge_.Increment(val); +} double Counter::Value() const { return gauge_.Value(); } diff --git a/core/src/gauge.cc b/core/src/gauge.cc index 05651b41..806483f5 100644 --- a/core/src/gauge.cc +++ b/core/src/gauge.cc @@ -9,18 +9,12 @@ Gauge::Gauge(const double value) : value_{value} {} void Gauge::Increment() { Increment(1.0); } void Gauge::Increment(const double value) { - if (value < 0.0) { - return; - } Change(value); } void Gauge::Decrement() { Decrement(1.0); } void Gauge::Decrement(const double value) { - if (value < 0.0) { - return; - } Change(-1.0 * value); } diff --git a/core/tests/gauge_test.cc b/core/tests/gauge_test.cc index 0183f761..f4f2b48a 100644 --- a/core/tests/gauge_test.cc +++ b/core/tests/gauge_test.cc @@ -32,9 +32,8 @@ TEST(GaugeTest, inc_multiple) { TEST(GaugeTest, inc_negative_value) { Gauge gauge; - gauge.Increment(5.0); - gauge.Increment(-5.0); - EXPECT_EQ(gauge.Value(), 5.0); + gauge.Increment(-1.0); + EXPECT_EQ(gauge.Value(), -1.0); } TEST(GaugeTest, dec) { @@ -46,9 +45,8 @@ TEST(GaugeTest, dec) { TEST(GaugeTest, dec_negative_value) { Gauge gauge; - gauge.Set(5.0); gauge.Decrement(-1.0); - EXPECT_EQ(gauge.Value(), 5.0); + EXPECT_EQ(gauge.Value(), 1.0); } TEST(GaugeTest, dec_number) { From efce85d54ab4f8464682362d990705eef4566dcc Mon Sep 17 00:00:00 2001 From: Dominik Charousset Date: Fri, 3 Jul 2020 18:32:18 +0200 Subject: [PATCH 113/206] Use a gauge for the histogram sum The online docs for Prometheus state: > The sum of observations (...) behaves like a counter, too, as long as > there are no negative observations. A counter can only ever go up and asserts that users pass in only positive values when incrementing. Hence, the `sum` must use a gauge in order to stay consistent with the Prometheus documentation. --- core/include/prometheus/histogram.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/include/prometheus/histogram.h b/core/include/prometheus/histogram.h index c727f3d6..a24ebde6 100644 --- a/core/include/prometheus/histogram.h +++ b/core/include/prometheus/histogram.h @@ -4,6 +4,7 @@ #include "prometheus/client_metric.h" #include "prometheus/counter.h" +#include "prometheus/gauge.h" #include "prometheus/detail/builder.h" #include "prometheus/detail/core_export.h" #include "prometheus/metric_type.h" @@ -19,7 +20,7 @@ namespace prometheus { /// values, allowing to calculate the average of the observed values. /// /// At its core a histogram has a counter per bucket. The sum of observations -/// also behaves like a counter. +/// also behaves like a counter as long as there are no negative observations. /// /// See https://prometheus.io/docs/practices/histograms/ for detailed /// explanations of histogram usage and differences to summaries. @@ -68,7 +69,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Histogram { private: const BucketBoundaries bucket_boundaries_; std::vector bucket_counts_; - Counter sum_; + Gauge sum_; }; /// \brief Return a builder to configure and register a Histogram metric. From 6d86e2db65098f47198db54a9fb71e89e59f6c21 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 1 Nov 2020 12:11:54 +0100 Subject: [PATCH 114/206] core: Add test for negative observed histogram value Fixes: #386 --- core/include/prometheus/histogram.h | 2 +- core/tests/histogram_test.cc | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/core/include/prometheus/histogram.h b/core/include/prometheus/histogram.h index a24ebde6..c720609a 100644 --- a/core/include/prometheus/histogram.h +++ b/core/include/prometheus/histogram.h @@ -4,9 +4,9 @@ #include "prometheus/client_metric.h" #include "prometheus/counter.h" -#include "prometheus/gauge.h" #include "prometheus/detail/builder.h" #include "prometheus/detail/core_export.h" +#include "prometheus/gauge.h" #include "prometheus/metric_type.h" namespace prometheus { diff --git a/core/tests/histogram_test.cc b/core/tests/histogram_test.cc index 9e2793fb..bcdda385 100644 --- a/core/tests/histogram_test.cc +++ b/core/tests/histogram_test.cc @@ -108,5 +108,13 @@ TEST(HistogramTest, observe_multiple_test_length_error) { ASSERT_THROW(histogram.ObserveMultiple({5, 9}, 20), std::length_error); } +TEST(HistogramTest, sum_can_go_down) { + Histogram histogram{{1}}; + auto metric1 = histogram.Collect(); + histogram.Observe(-10); + auto metric2 = histogram.Collect(); + EXPECT_LT(metric2.histogram.sample_sum, metric1.histogram.sample_sum); +} + } // namespace } // namespace prometheus From 01c11d5bd61910653eb2d3124b604e80dbfc9987 Mon Sep 17 00:00:00 2001 From: Jupp Mueller Date: Fri, 6 Nov 2020 09:53:23 -0800 Subject: [PATCH 115/206] Fix insufficiently precise value rendering This change fixes #407 by increasing precision for rendered floating point numbers output in the text serializer. --- core/src/text_serializer.cc | 10 ++++++++-- core/tests/text_serializer_test.cc | 14 +++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/core/src/text_serializer.cc b/core/src/text_serializer.cc index 4da59ad2..ee5c0e14 100644 --- a/core/src/text_serializer.cc +++ b/core/src/text_serializer.cc @@ -1,6 +1,7 @@ #include "prometheus/text_serializer.h" #include +#include #include #include #include @@ -16,9 +17,14 @@ void WriteValue(std::ostream& out, double value) { } else if (std::isinf(value)) { out << (value < 0 ? "-Inf" : "+Inf"); } else { - auto saved_flags = out.setf(std::ios::fixed, std::ios::floatfield); + std::ios oldState{nullptr}; + oldState.copyfmt(out); + + out.setf(std::ios::fixed, std::ios::floatfield); + out << std::setprecision(17); out << value; - out.setf(saved_flags, std::ios::floatfield); + + out.copyfmt(oldState); } } diff --git a/core/tests/text_serializer_test.cc b/core/tests/text_serializer_test.cc index edd0477e..3de00c19 100644 --- a/core/tests/text_serializer_test.cc +++ b/core/tests/text_serializer_test.cc @@ -69,7 +69,7 @@ TEST_F(TextSerializerTest, shouldSerializeUntyped) { metric.untyped.value = 64.0; const auto serialized = Serialize(MetricType::Untyped); - EXPECT_THAT(serialized, testing::HasSubstr(name + " 64.000000")); + EXPECT_THAT(serialized, testing::HasSubstr(name + " 64.00000000000000000")); } TEST_F(TextSerializerTest, shouldSerializeTimestamp) { @@ -77,7 +77,7 @@ TEST_F(TextSerializerTest, shouldSerializeTimestamp) { metric.timestamp_ms = 1234; const auto serialized = Serialize(MetricType::Counter); - EXPECT_THAT(serialized, testing::HasSubstr(name + " 64.000000 1234")); + EXPECT_THAT(serialized, testing::HasSubstr(name + " 64.00000000000000000 1234")); } TEST_F(TextSerializerTest, shouldSerializeHistogramWithNoBuckets) { @@ -86,7 +86,7 @@ TEST_F(TextSerializerTest, shouldSerializeHistogramWithNoBuckets) { const auto serialized = Serialize(MetricType::Histogram); EXPECT_THAT(serialized, testing::HasSubstr(name + "_count 2")); - EXPECT_THAT(serialized, testing::HasSubstr(name + "_sum 32.00000")); + EXPECT_THAT(serialized, testing::HasSubstr(name + "_sum 32.000000000000000")); EXPECT_THAT(serialized, testing::HasSubstr(name + "_bucket{le=\"+Inf\"} 2")); } @@ -98,9 +98,9 @@ TEST_F(TextSerializerTest, shouldSerializeHistogram) { const auto serialized = Serialize(MetricType::Histogram); EXPECT_THAT(serialized, testing::HasSubstr(name + "_count 2")); - EXPECT_THAT(serialized, testing::HasSubstr(name + "_sum 200.00000")); + EXPECT_THAT(serialized, testing::HasSubstr(name + "_sum 200.00000000000000")); EXPECT_THAT(serialized, - testing::HasSubstr(name + "_bucket{le=\"1.000000\"} 1")); + testing::HasSubstr(name + "_bucket{le=\"1.00000000000000000\"} 1")); EXPECT_THAT(serialized, testing::HasSubstr(name + "_bucket{le=\"+Inf\"} 2")); } @@ -112,9 +112,9 @@ TEST_F(TextSerializerTest, shouldSerializeSummary) { const auto serialized = Serialize(MetricType::Summary); EXPECT_THAT(serialized, testing::HasSubstr(name + "_count 2")); - EXPECT_THAT(serialized, testing::HasSubstr(name + "_sum 200.00000")); + EXPECT_THAT(serialized, testing::HasSubstr(name + "_sum 200.00000000000000")); EXPECT_THAT(serialized, - testing::HasSubstr(name + "{quantile=\"0.500000\"} 0.000000")); + testing::HasSubstr(name + "{quantile=\"0.50000000000000000\"} 0.0000000000000000")); } } // namespace From ce07a38d4c630ac1958d4c22b1b999dca8958c6f Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Wed, 11 Nov 2020 17:51:27 +0100 Subject: [PATCH 116/206] feat: allow selection of MSVC runtime library to select the static runtime use at least CMake 3.15 and pass `-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded$<$:Debug>` to CMake when configuring. Fixes: #410 --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 96056e04..bbacb42d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,8 @@ cmake_minimum_required(VERSION 3.12 FATAL_ERROR) +if(POLICY CMP0091) + cmake_policy(SET CMP0091 NEW) # recognize CMAKE_MSVC_RUNTIME_LIBRARY +endif() project(prometheus-cpp VERSION 0.10.0) From 80513483a24c6e82a3df436893bbfa186222bca4 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 15 Nov 2020 19:52:37 +0100 Subject: [PATCH 117/206] chore: use max_digits10 instead of magic number --- core/src/text_serializer.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/text_serializer.cc b/core/src/text_serializer.cc index ee5c0e14..c0267941 100644 --- a/core/src/text_serializer.cc +++ b/core/src/text_serializer.cc @@ -21,7 +21,7 @@ void WriteValue(std::ostream& out, double value) { oldState.copyfmt(out); out.setf(std::ios::fixed, std::ios::floatfield); - out << std::setprecision(17); + out << std::setprecision(std::numeric_limits::max_digits10); out << value; out.copyfmt(oldState); From f40788927eee31b8858c8b982f9b74be3aa8800f Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 15 Nov 2020 20:26:55 +0100 Subject: [PATCH 118/206] build: Bump library interface due to changes Histogram class --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bbacb42d..d7759775 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ if(POLICY CMP0091) cmake_policy(SET CMP0091 NEW) # recognize CMAKE_MSVC_RUNTIME_LIBRARY endif() -project(prometheus-cpp VERSION 0.10.0) +project(prometheus-cpp VERSION 0.11.0) include(GenerateExportHeader) include(GNUInstallDirs) From 72b4d199436dcd60b112c0e58bb400b555f6d988 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 15 Nov 2020 20:23:16 +0100 Subject: [PATCH 119/206] pull: work-around missing winsock lib in civetweb Fixes: #401 --- pull/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pull/CMakeLists.txt b/pull/CMakeLists.txt index 800daeca..4349f007 100644 --- a/pull/CMakeLists.txt +++ b/pull/CMakeLists.txt @@ -14,6 +14,12 @@ if(USE_THIRDPARTY_LIBRARIES) else() find_package(civetweb CONFIG REQUIRED) find_package(cppcodec REQUIRED) + + # work-around https://github.com/civetweb/civetweb/pull/918 + if(WIN32 AND NOT TARGET WINSOCK::WINSOCK) + add_library(WINSOCK::WINSOCK INTERFACE IMPORTED) + target_link_libraries(WINSOCK::WINSOCK INTERFACE ws2_32) + endif() endif() if(ENABLE_COMPRESSION) From bb017ec15a824d3301845a1274b4b46a01d6d871 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Mon, 23 Nov 2020 23:44:04 +0100 Subject: [PATCH 120/206] pull: Use internal base64 decoding function to avoid dependency (#417) --- .github/scripts/run-prepare | 2 +- .github/scripts/run-prepare.cmd | 2 +- .gitmodules | 3 - 3rdparty/cppcodec | 1 - bazel/cppcodec.BUILD | 6 -- bazel/repositories.bzl | 11 ---- cmake/Findcppcodec.cmake | 8 --- cmake/cppcodec-3rdparty-config.cmake | 14 ----- pull/BUILD.bazel | 13 +++- pull/CMakeLists.txt | 15 ++--- pull/src/basic_auth.cc | 7 +-- pull/src/detail/base64.h | 88 ++++++++++++++++++++++++++++ pull/tests/CMakeLists.txt | 1 + pull/tests/internal/BUILD.bazel | 13 ++++ pull/tests/internal/CMakeLists.txt | 14 +++++ pull/tests/internal/base64_test.cc | 49 ++++++++++++++++ 16 files changed, 187 insertions(+), 60 deletions(-) delete mode 160000 3rdparty/cppcodec delete mode 100644 bazel/cppcodec.BUILD delete mode 100644 cmake/Findcppcodec.cmake delete mode 100644 cmake/cppcodec-3rdparty-config.cmake create mode 100644 pull/src/detail/base64.h create mode 100644 pull/tests/internal/BUILD.bazel create mode 100644 pull/tests/internal/CMakeLists.txt create mode 100644 pull/tests/internal/base64_test.cc diff --git a/.github/scripts/run-prepare b/.github/scripts/run-prepare index 5b5fafc9..0fbe1045 100755 --- a/.github/scripts/run-prepare +++ b/.github/scripts/run-prepare @@ -34,6 +34,6 @@ esac case "${BUILDSYSTEM_ARG}" in cmake) - "${VCPKG_INSTALLATION_ROOT}/vcpkg" install benchmark civetweb cppcodec curl gtest zlib + "${VCPKG_INSTALLATION_ROOT}/vcpkg" install benchmark civetweb curl gtest zlib ;; esac diff --git a/.github/scripts/run-prepare.cmd b/.github/scripts/run-prepare.cmd index 0302a028..ec14d92f 100644 --- a/.github/scripts/run-prepare.cmd +++ b/.github/scripts/run-prepare.cmd @@ -1,4 +1,4 @@ if [%1] == [cmake] ( - %VCPKG_INSTALLATION_ROOT%/vcpkg install benchmark civetweb cppcodec curl gtest zlib || EXIT /B 1 + %VCPKG_INSTALLATION_ROOT%/vcpkg install benchmark civetweb curl gtest zlib || EXIT /B 1 ) diff --git a/.gitmodules b/.gitmodules index f7541b36..ccfd018a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,6 +4,3 @@ [submodule "civetweb"] path = 3rdparty/civetweb url = https://github.com/civetweb/civetweb.git -[submodule "3rdparty/cppcodec"] - path = 3rdparty/cppcodec - url = https://github.com/tplgy/cppcodec.git diff --git a/3rdparty/cppcodec b/3rdparty/cppcodec deleted file mode 160000 index 302dc28f..00000000 --- a/3rdparty/cppcodec +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 302dc28f8fd5c8bf2ea8d7212aed3be884d5d166 diff --git a/bazel/cppcodec.BUILD b/bazel/cppcodec.BUILD deleted file mode 100644 index ecde0e88..00000000 --- a/bazel/cppcodec.BUILD +++ /dev/null @@ -1,6 +0,0 @@ -cc_library( - name = "cppcodec", - hdrs = glob(["cppcodec/**/*.hpp"]), - includes = ["."], - visibility = ["//visibility:public"], -) diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index 1d92596c..fe35ee0b 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -45,17 +45,6 @@ def prometheus_cpp_repositories(): ], ) - maybe( - http_archive, - name = "com_github_tplgy_cppcodec", - sha256 = "0edaea2a9d9709d456aa99a1c3e17812ed130f9ef2b5c2d152c230a5cbc5c482", - strip_prefix = "cppcodec-0.2", - urls = [ - "https://github.com/tplgy/cppcodec/archive/v0.2.tar.gz", - ], - build_file = "@com_github_jupp0r_prometheus_cpp//bazel:cppcodec.BUILD", - ) - maybe( http_archive, name = "net_zlib_zlib", diff --git a/cmake/Findcppcodec.cmake b/cmake/Findcppcodec.cmake deleted file mode 100644 index 9c3e7b37..00000000 --- a/cmake/Findcppcodec.cmake +++ /dev/null @@ -1,8 +0,0 @@ -find_path(CPPCODEC_INCLUDE_DIR base64_rfc4648.hpp PATH_SUFFIXES include/cppcodec) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(cppcodec DEFAULT_MSG CPPCODEC_INCLUDE_DIR) - -if(cppcodec_FOUND) - set(CPPCODEC_INCLUDE_DIRS "${CPPCODEC_INCLUDE_DIR}") -endif() diff --git a/cmake/cppcodec-3rdparty-config.cmake b/cmake/cppcodec-3rdparty-config.cmake deleted file mode 100644 index fd4be810..00000000 --- a/cmake/cppcodec-3rdparty-config.cmake +++ /dev/null @@ -1,14 +0,0 @@ -get_filename_component(_IMPORT_PREFIX "${PROJECT_SOURCE_DIR}/3rdparty/cppcodec/" ABSOLUTE) - -macro(set_and_check _var _file) - set(${_var} "${_file}") - if(NOT EXISTS "${_file}") - message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !") - endif() -endmacro() - -set_and_check(CPPCODEC_INCLUDE_DIR ${_IMPORT_PREFIX}) -set(CPPCODEC_INCLUDE_DIRS "${CPPCODEC_INCLUDE_DIR}") - -add_library(cppcodec INTERFACE) -target_include_directories(cppcodec INTERFACE "$") diff --git a/pull/BUILD.bazel b/pull/BUILD.bazel index 241df1b3..1e6e9250 100644 --- a/pull/BUILD.bazel +++ b/pull/BUILD.bazel @@ -23,7 +23,18 @@ cc_library( deps = [ "//core", "@civetweb", - "@com_github_tplgy_cppcodec//:cppcodec", "@net_zlib_zlib//:z", ], ) + +cc_library( + name = "pull_internal_headers", + hdrs = glob( + ["src/detail/*.h"], + ), + strip_include_prefix = "src", + visibility = ["//pull/tests:__subpackages__"], + deps = [ + "//core", + ], +) diff --git a/pull/CMakeLists.txt b/pull/CMakeLists.txt index 4349f007..6dfa6a2f 100644 --- a/pull/CMakeLists.txt +++ b/pull/CMakeLists.txt @@ -5,15 +5,8 @@ if(USE_THIRDPARTY_LIBRARIES) TARGETS civetweb EXPORT ${PROJECT_NAME}-targets ) - find_package(cppcodec-3rdparty CONFIG REQUIRED) - add_library(${PROJECT_NAME}::cppcodec ALIAS cppcodec) - install( - TARGETS cppcodec - EXPORT ${PROJECT_NAME}-targets - ) else() find_package(civetweb CONFIG REQUIRED) - find_package(cppcodec REQUIRED) # work-around https://github.com/civetweb/civetweb/pull/918 if(WIN32 AND NOT TARGET WINSOCK::WINSOCK) @@ -36,6 +29,8 @@ add_library(pull src/handler.h src/metrics_collector.cc src/metrics_collector.h + + src/detail/base64.h ) add_library(${PROJECT_NAME}::pull ALIAS pull) @@ -46,7 +41,6 @@ target_link_libraries(pull PRIVATE Threads::Threads $,${PROJECT_NAME}::civetweb,civetweb::civetweb-cpp> - $<$:${PROJECT_NAME}::cppcodec> $<$,$>>:rt> $<$:ZLIB::ZLIB> ) @@ -56,7 +50,6 @@ target_include_directories(pull $ $ PRIVATE - ${CPPCODEC_INCLUDE_DIRS} # needed as long as upstream cppcodec installs no config file with imported target ${CIVETWEB_INCLUDE_DIRS} ) @@ -93,5 +86,9 @@ install( ) if(ENABLE_TESTING) + add_library(pull_internal_headers INTERFACE) + add_library(${PROJECT_NAME}::pull_internal_headers ALIAS pull_internal_headers) + target_include_directories(pull_internal_headers INTERFACE src) + add_subdirectory(tests) endif() diff --git a/pull/src/basic_auth.cc b/pull/src/basic_auth.cc index 5e562b50..7bae3ca4 100644 --- a/pull/src/basic_auth.cc +++ b/pull/src/basic_auth.cc @@ -1,14 +1,11 @@ #include "basic_auth.h" -#include - #include "CivetServer.h" +#include "detail/base64.h" #include "prometheus/detail/future_std.h" namespace prometheus { -using base64 = cppcodec::base64_rfc4648; - BasicAuthHandler::BasicAuthHandler(AuthFunc callback, std::string realm) : callback_(std::move(callback)), realm_(std::move(realm)) {} @@ -42,7 +39,7 @@ bool BasicAuthHandler::AuthorizeInner(CivetServer*, mg_connection* conn) { std::string decoded; try { - decoded = base64::decode(b64Auth.data(), b64Auth.size()); + decoded = detail::base64_decode(b64Auth); } catch (...) { return false; } diff --git a/pull/src/detail/base64.h b/pull/src/detail/base64.h new file mode 100644 index 00000000..256dcc39 --- /dev/null +++ b/pull/src/detail/base64.h @@ -0,0 +1,88 @@ +#pragma once + +#include +#include +#include + +namespace prometheus { +namespace detail { + +/* +Copyright (C) 2019-2020 by Martin Vorbrodt + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + +https://github.com/mvorbrodt/blog/blob/master/src/base64.hpp +*/ + +inline std::string base64_decode(const std::string& input) { + const char kPadCharacter = '='; + + if (input.length() % 4) { + throw std::runtime_error("Invalid base64 length!"); + } + + std::size_t padding = 0; + + if (!input.empty()) { + if (input[input.length() - 1] == kPadCharacter) padding++; + if (input[input.length() - 2] == kPadCharacter) padding++; + } + + std::string decoded; + decoded.reserve(((input.length() / 4) * 3) - padding); + + std::uint32_t temp = 0; + auto it = input.begin(); + + while (it < input.end()) { + for (std::size_t i = 0; i < 4; ++i) { + temp <<= 6; + if (*it >= 0x41 && *it <= 0x5A) { + temp |= *it - 0x41; + } else if (*it >= 0x61 && *it <= 0x7A) { + temp |= *it - 0x47; + } else if (*it >= 0x30 && *it <= 0x39) { + temp |= *it + 0x04; + } else if (*it == 0x2B) { + temp |= 0x3E; + } else if (*it == 0x2F) { + temp |= 0x3F; + } else if (*it == kPadCharacter) { + switch (input.end() - it) { + case 1: + decoded.push_back((temp >> 16) & 0x000000FF); + decoded.push_back((temp >> 8) & 0x000000FF); + return decoded; + case 2: + decoded.push_back((temp >> 10) & 0x000000FF); + return decoded; + default: + throw std::runtime_error("Invalid padding in base64!"); + } + } else { + throw std::runtime_error("Invalid character in base64!"); + } + + ++it; + } + + decoded.push_back((temp >> 16) & 0x000000FF); + decoded.push_back((temp >> 8) & 0x000000FF); + decoded.push_back((temp)&0x000000FF); + } + + return decoded; +} + +} // namespace detail +} // namespace prometheus diff --git a/pull/tests/CMakeLists.txt b/pull/tests/CMakeLists.txt index 729c6ee0..bb92342e 100644 --- a/pull/tests/CMakeLists.txt +++ b/pull/tests/CMakeLists.txt @@ -1,2 +1,3 @@ add_subdirectory(integration) +add_subdirectory(internal) add_subdirectory(unit) diff --git a/pull/tests/internal/BUILD.bazel b/pull/tests/internal/BUILD.bazel new file mode 100644 index 00000000..f6967b17 --- /dev/null +++ b/pull/tests/internal/BUILD.bazel @@ -0,0 +1,13 @@ +cc_test( + name = "internal", + srcs = glob([ + "*.cc", + "*.h", + ]), + copts = ["-Iexternal/googletest/include"], + linkstatic = True, + deps = [ + "//pull:pull_internal_headers", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/pull/tests/internal/CMakeLists.txt b/pull/tests/internal/CMakeLists.txt new file mode 100644 index 00000000..87489021 --- /dev/null +++ b/pull/tests/internal/CMakeLists.txt @@ -0,0 +1,14 @@ +add_executable(prometheus_pull_internal_test + base64_test.cc +) + +target_link_libraries(prometheus_pull_internal_test + PRIVATE + ${PROJECT_NAME}::pull_internal_headers + GTest::gmock_main +) + +add_test( + NAME prometheus_pull_internal_test + COMMAND prometheus_pull_internal_test +) diff --git a/pull/tests/internal/base64_test.cc b/pull/tests/internal/base64_test.cc new file mode 100644 index 00000000..980e8c96 --- /dev/null +++ b/pull/tests/internal/base64_test.cc @@ -0,0 +1,49 @@ +#include "detail/base64.h" + +#include + +#include + +namespace prometheus { +namespace { + +struct TestVector { + const std::string decoded; + const std::string encoded; +}; + +const TestVector testVector[] = { + {"", ""}, + {"f", "Zg=="}, + {"fo", "Zm8="}, + {"foo", "Zm9v"}, + {"foob", "Zm9vYg=="}, + {"fooba", "Zm9vYmE="}, + {"foobar", "Zm9vYmFy"}, +}; + +const unsigned nVectors = sizeof(testVector) / sizeof(testVector[0]); + +using namespace testing; + +TEST(Base64Test, decodeTest) { + for (unsigned i = 0; i < nVectors; ++i) { + std::string decoded = detail::base64_decode(testVector[i].encoded); + EXPECT_EQ(testVector[i].decoded, decoded); + } +} + +TEST(Base64Test, rejectInvalidSymbols) { + EXPECT_ANY_THROW(detail::base64_decode("....")); +} + +TEST(Base64Test, rejectInvalidInputSize) { + EXPECT_ANY_THROW(detail::base64_decode("ABC")); +} + +TEST(Base64Test, rejectInvalidPadding) { + EXPECT_ANY_THROW(detail::base64_decode("A===")); +} + +} // namespace +} // namespace prometheus From d841f00378c1188e4efd10deed2b07eca74d9d66 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 13 Dec 2020 16:46:21 +0100 Subject: [PATCH 121/206] core: enforce proper metric and label names Closes: #421 --- core/include/prometheus/family.h | 2 ++ core/src/family.cc | 36 ++++++++++++++++++++------------ core/tests/check_names_test.cc | 4 +++- core/tests/family_test.cc | 18 ++++++++++------ 4 files changed, 40 insertions(+), 20 deletions(-) diff --git a/core/include/prometheus/family.h b/core/include/prometheus/family.h index aa946832..df282f12 100644 --- a/core/include/prometheus/family.h +++ b/core/include/prometheus/family.h @@ -88,6 +88,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Family : public Collectable { /// \param constant_labels Assign a set of key-value pairs (= labels) to the /// metric. All these labels are propagated to each time series within the /// metric. + /// \throw std::runtime_exception on invalid metric or label names. Family(const std::string& name, const std::string& help, const std::map& constant_labels); @@ -107,6 +108,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Family : public Collectable { /// Counter, Gauge, Histogram or Summary for required constructor arguments. /// \return Return the newly created dimensional data or - if a same set of /// labels already exists - the already existing dimensional data. + /// \throw std::runtime_exception on invalid label names. template T& Add(const std::map& labels, Args&&... args) { return Add(labels, detail::make_unique(args...)); diff --git a/core/src/family.cc b/core/src/family.cc index 83631abc..a28916bb 100644 --- a/core/src/family.cc +++ b/core/src/family.cc @@ -5,13 +5,23 @@ #include "prometheus/histogram.h" #include "prometheus/summary.h" +#include + namespace prometheus { template Family::Family(const std::string& name, const std::string& help, const std::map& constant_labels) : name_(name), help_(help), constant_labels_(constant_labels) { - assert(CheckMetricName(name_)); + if (!CheckMetricName(name_)) { + throw std::invalid_argument("Invalid metric name"); + } + for (auto& label_pair : constant_labels_) { + auto& label_name = label_pair.first; + if (!CheckLabelName(label_name)) { + throw std::invalid_argument("Invalid label name"); + } + } } template @@ -29,20 +39,20 @@ T& Family::Add(const std::map& labels, assert(labels == old_labels); #endif return *metrics_iter->second; - } else { -#ifndef NDEBUG - for (auto& label_pair : labels) { - auto& label_name = label_pair.first; - assert(CheckLabelName(label_name)); - } -#endif + } - auto metric = metrics_.insert(std::make_pair(hash, std::move(object))); - assert(metric.second); - labels_.insert({hash, labels}); - labels_reverse_lookup_.insert({metric.first->second.get(), hash}); - return *(metric.first->second); + for (auto& label_pair : labels) { + auto& label_name = label_pair.first; + if (!CheckLabelName(label_name)) { + throw std::invalid_argument("Invalid label name"); + } } + + auto metric = metrics_.insert(std::make_pair(hash, std::move(object))); + assert(metric.second); + labels_.insert({hash, labels}); + labels_reverse_lookup_.insert({metric.first->second.get(), hash}); + return *(metric.first->second); } template diff --git a/core/tests/check_names_test.cc b/core/tests/check_names_test.cc index 8d694507..aa6c77a9 100644 --- a/core/tests/check_names_test.cc +++ b/core/tests/check_names_test.cc @@ -12,7 +12,9 @@ TEST(CheckNamesTest, good_metric_name) { TEST(CheckNamesTest, reserved_metric_name) { EXPECT_FALSE(CheckMetricName("__some_reserved_metric")); } - +TEST(CheckNamesTest, malformed_metric_name) { + EXPECT_FALSE(CheckMetricName("fa mi ly with space in name or |")); +} TEST(CheckNamesTest, empty_label_name) { EXPECT_FALSE(CheckLabelName("")); } TEST(CheckNamesTest, good_label_name) { EXPECT_TRUE(CheckLabelName("type")); } TEST(CheckNamesTest, reserved_label_name) { diff --git a/core/tests/family_test.cc b/core/tests/family_test.cc index 8f11e5a5..a311e9fc 100644 --- a/core/tests/family_test.cc +++ b/core/tests/family_test.cc @@ -69,22 +69,28 @@ TEST(FamilyTest, add_twice) { ASSERT_EQ(&counter, &counter1); } -TEST(FamilyTest, should_assert_on_invalid_metric_name) { +TEST(FamilyTest, throw_on_invalid_metric_name) { auto create_family_with_invalid_name = []() { return detail::make_unique>( "", "empty name", std::map{}); }; - EXPECT_DEBUG_DEATH(create_family_with_invalid_name(), - ".*Assertion .*CheckMetricName.*"); + EXPECT_ANY_THROW(create_family_with_invalid_name()); } -TEST(FamilyTest, should_assert_on_invalid_labels) { +TEST(FamilyTest, throw_on_invalid_constant_label_name) { + auto create_family_with_invalid_labels = []() { + return detail::make_unique>( + "total_requests", "Counts all requests", std::map{{"__inavlid", "counter1"}}); + }; + EXPECT_ANY_THROW(create_family_with_invalid_labels()); +} + +TEST(FamilyTest, should_throw_on_invalid_labels) { Family family{"total_requests", "Counts all requests", {}}; auto add_metric_with_invalid_label_name = [&family]() { family.Add({{"__invalid", "counter1"}}); }; - EXPECT_DEBUG_DEATH(add_metric_with_invalid_label_name(), - ".*Assertion .*CheckLabelName.*"); + EXPECT_ANY_THROW(add_metric_with_invalid_label_name()); } } // namespace From 1101626fb7a35a396c8c21b1099a5a91729cecd0 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 13 Dec 2020 16:58:53 +0100 Subject: [PATCH 122/206] pull: do not export BasicAuthHandler --- pull/src/basic_auth.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pull/src/basic_auth.h b/pull/src/basic_auth.h index 895f90ea..87109dbf 100644 --- a/pull/src/basic_auth.h +++ b/pull/src/basic_auth.h @@ -12,7 +12,7 @@ namespace prometheus { /** * Handler for HTTP Basic authentication for Endpoints. */ -class PROMETHEUS_CPP_PULL_EXPORT BasicAuthHandler : public CivetAuthHandler { +class BasicAuthHandler : public CivetAuthHandler { public: using AuthFunc = std::function; explicit BasicAuthHandler(AuthFunc callback, std::string realm); From acab56c8081c3a9995331f1999f2d698ce341b52 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Mon, 14 Dec 2020 20:05:20 +0100 Subject: [PATCH 123/206] chore: re-format with clang-format 11 --- cmake/project-import/sample_client.cc | 66 ++++++++++++++++++++++++- core/benchmarks/benchmark_helpers.cc | 4 +- core/benchmarks/histogram_bench.cc | 6 +-- core/benchmarks/registry_bench.cc | 4 +- core/benchmarks/summary_bench.cc | 6 +-- core/src/detail/hash.h | 4 +- core/src/detail/utils.cc | 3 +- core/src/family.cc | 4 +- core/src/gauge.cc | 8 +-- core/src/histogram.cc | 4 +- core/src/registry.cc | 4 +- core/tests/builder_test.cc | 7 +-- core/tests/family_test.cc | 7 +-- core/tests/histogram_test.cc | 4 +- core/tests/registry_test.cc | 9 ++-- core/tests/serializer_test.cc | 11 ++--- core/tests/summary_test.cc | 4 +- core/tests/text_serializer_test.cc | 13 +++-- core/tests/utils_test.cc | 1 + push/tests/integration/sample_client.cc | 8 +-- 20 files changed, 121 insertions(+), 56 deletions(-) mode change 120000 => 100644 cmake/project-import/sample_client.cc diff --git a/cmake/project-import/sample_client.cc b/cmake/project-import/sample_client.cc deleted file mode 120000 index 4c67af80..00000000 --- a/cmake/project-import/sample_client.cc +++ /dev/null @@ -1 +0,0 @@ -../../push/tests/integration/sample_client.cc \ No newline at end of file diff --git a/cmake/project-import/sample_client.cc b/cmake/project-import/sample_client.cc new file mode 100644 index 00000000..03414fe9 --- /dev/null +++ b/cmake/project-import/sample_client.cc @@ -0,0 +1,65 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#else +#include +#include +#endif + +static std::string GetHostName() { + char hostname[1024]; + + if (::gethostname(hostname, sizeof(hostname))) { + return {}; + } + return hostname; +} + +int main() { + using namespace prometheus; + + // create a push gateway + const auto labels = Gateway::GetInstanceLabel(GetHostName()); + + Gateway gateway{"127.0.0.1", "9091", "sample_client", labels}; + + // create a metrics registry with component=main labels applied to all its + // metrics + auto registry = std::make_shared(); + + // add a new counter family to the registry (families combine values with the + // same name, but distinct label dimensions) + auto& counter_family = BuildCounter() + .Name("time_running_seconds_total") + .Help("How many seconds is this server running?") + .Labels({{"label", "value"}}) + .Register(*registry); + + // add a counter to the metric family + auto& second_counter = counter_family.Add( + {{"another_label", "value"}, {"yet_another_label", "value"}}); + + // ask the pusher to push the metrics to the pushgateway + gateway.RegisterCollectable(registry); + + for (;;) { + std::this_thread::sleep_for(std::chrono::seconds(1)); + // increment the counter by one (second) + second_counter.Increment(); + + // push metrics + auto returnCode = gateway.Push(); + std::cout << "returnCode is " << returnCode << std::endl; + } + return 0; +} diff --git a/core/benchmarks/benchmark_helpers.cc b/core/benchmarks/benchmark_helpers.cc index 12cb5a20..8585b204 100644 --- a/core/benchmarks/benchmark_helpers.cc +++ b/core/benchmarks/benchmark_helpers.cc @@ -1,8 +1,8 @@ +#include "benchmark_helpers.h" + #include #include -#include "benchmark_helpers.h" - std::string GenerateRandomString(size_t length) { auto randchar = []() -> char { const char charset[] = "abcdefghijklmnopqrstuvwxyz"; diff --git a/core/benchmarks/histogram_bench.cc b/core/benchmarks/histogram_bench.cc index 5f48971c..54458e68 100644 --- a/core/benchmarks/histogram_bench.cc +++ b/core/benchmarks/histogram_bench.cc @@ -1,10 +1,10 @@ -#include -#include - #include #include #include +#include +#include + using prometheus::Histogram; static Histogram::BucketBoundaries CreateLinearBuckets(double start, double end, diff --git a/core/benchmarks/registry_bench.cc b/core/benchmarks/registry_bench.cc index ea74ef24..67054da0 100644 --- a/core/benchmarks/registry_bench.cc +++ b/core/benchmarks/registry_bench.cc @@ -1,9 +1,9 @@ -#include - #include #include #include +#include + #include "benchmark_helpers.h" static void BM_Registry_CreateFamily(benchmark::State& state) { diff --git a/core/benchmarks/summary_bench.cc b/core/benchmarks/summary_bench.cc index 2a55ef95..d19c4cdc 100644 --- a/core/benchmarks/summary_bench.cc +++ b/core/benchmarks/summary_bench.cc @@ -1,10 +1,10 @@ -#include -#include - #include #include #include +#include +#include + using prometheus::Summary; static const auto ITERATIONS = 262144; diff --git a/core/src/detail/hash.h b/core/src/detail/hash.h index bfa54483..da415dbd 100644 --- a/core/src/detail/hash.h +++ b/core/src/detail/hash.h @@ -29,7 +29,7 @@ inline void hash_combine(std::size_t *seed, const T &value) { /// \param args The objects that will be combined with the given hash value. template inline void hash_combine(std::size_t *seed, const T &value, - const Types &... args) { + const Types &...args) { hash_combine(seed, value); hash_combine(seed, args...); } @@ -39,7 +39,7 @@ inline void hash_combine(std::size_t *seed, const T &value, /// \param args The arguments that will be computed hash value. /// \return The hash value of the given args. template -inline std::size_t hash_value(const Types &... args) { +inline std::size_t hash_value(const Types &...args) { std::size_t seed = 0; hash_combine(&seed, args...); return seed; diff --git a/core/src/detail/utils.cc b/core/src/detail/utils.cc index 80f557ef..754ddc2d 100644 --- a/core/src/detail/utils.cc +++ b/core/src/detail/utils.cc @@ -1,8 +1,9 @@ #include "prometheus/detail/utils.h" -#include "hash.h" #include +#include "hash.h" + namespace prometheus { namespace detail { diff --git a/core/src/family.cc b/core/src/family.cc index a28916bb..7ed5a1dc 100644 --- a/core/src/family.cc +++ b/core/src/family.cc @@ -1,12 +1,12 @@ #include "prometheus/family.h" +#include + #include "prometheus/counter.h" #include "prometheus/gauge.h" #include "prometheus/histogram.h" #include "prometheus/summary.h" -#include - namespace prometheus { template diff --git a/core/src/gauge.cc b/core/src/gauge.cc index 806483f5..b3933076 100644 --- a/core/src/gauge.cc +++ b/core/src/gauge.cc @@ -8,15 +8,11 @@ Gauge::Gauge(const double value) : value_{value} {} void Gauge::Increment() { Increment(1.0); } -void Gauge::Increment(const double value) { - Change(value); -} +void Gauge::Increment(const double value) { Change(value); } void Gauge::Decrement() { Decrement(1.0); } -void Gauge::Decrement(const double value) { - Change(-1.0 * value); -} +void Gauge::Decrement(const double value) { Change(-1.0 * value); } void Gauge::Set(const double value) { value_.store(value); } diff --git a/core/src/histogram.cc b/core/src/histogram.cc index 80235298..8445e231 100644 --- a/core/src/histogram.cc +++ b/core/src/histogram.cc @@ -36,9 +36,7 @@ void Histogram::ObserveMultiple(const std::vector& bucket_increments, sum_.Increment(sum_of_values); for (std::size_t i{0}; i < bucket_counts_.size(); ++i) { - { - bucket_counts_[i].Increment(bucket_increments[i]); - } + { bucket_counts_[i].Increment(bucket_increments[i]); } } } diff --git a/core/src/registry.cc b/core/src/registry.cc index 1a30a233..7f91472e 100644 --- a/core/src/registry.cc +++ b/core/src/registry.cc @@ -1,12 +1,12 @@ #include "prometheus/registry.h" +#include + #include "prometheus/counter.h" #include "prometheus/gauge.h" #include "prometheus/histogram.h" #include "prometheus/summary.h" -#include - namespace prometheus { namespace { diff --git a/core/tests/builder_test.cc b/core/tests/builder_test.cc index c7407b58..2bbc54c1 100644 --- a/core/tests/builder_test.cc +++ b/core/tests/builder_test.cc @@ -1,12 +1,13 @@ +#include + +#include + #include "prometheus/counter.h" #include "prometheus/gauge.h" #include "prometheus/histogram.h" #include "prometheus/registry.h" #include "prometheus/summary.h" -#include -#include - namespace prometheus { namespace { diff --git a/core/tests/family_test.cc b/core/tests/family_test.cc index a311e9fc..d68a6a21 100644 --- a/core/tests/family_test.cc +++ b/core/tests/family_test.cc @@ -1,9 +1,9 @@ #include "prometheus/family.h" -#include - #include +#include + #include "prometheus/client_metric.h" #include "prometheus/detail/future_std.h" #include "prometheus/histogram.h" @@ -80,7 +80,8 @@ TEST(FamilyTest, throw_on_invalid_metric_name) { TEST(FamilyTest, throw_on_invalid_constant_label_name) { auto create_family_with_invalid_labels = []() { return detail::make_unique>( - "total_requests", "Counts all requests", std::map{{"__inavlid", "counter1"}}); + "total_requests", "Counts all requests", + std::map{{"__inavlid", "counter1"}}); }; EXPECT_ANY_THROW(create_family_with_invalid_labels()); } diff --git a/core/tests/histogram_test.cc b/core/tests/histogram_test.cc index bcdda385..6c3b30df 100644 --- a/core/tests/histogram_test.cc +++ b/core/tests/histogram_test.cc @@ -1,9 +1,9 @@ #include "prometheus/histogram.h" -#include - #include +#include + namespace prometheus { namespace { diff --git a/core/tests/registry_test.cc b/core/tests/registry_test.cc index 5fb4a041..6a02981f 100644 --- a/core/tests/registry_test.cc +++ b/core/tests/registry_test.cc @@ -1,11 +1,12 @@ #include "prometheus/registry.h" -#include "prometheus/counter.h" -#include "prometheus/histogram.h" -#include "prometheus/summary.h" + +#include #include -#include +#include "prometheus/counter.h" +#include "prometheus/histogram.h" +#include "prometheus/summary.h" namespace prometheus { namespace { diff --git a/core/tests/serializer_test.cc b/core/tests/serializer_test.cc index 90550ee9..7e9e26a3 100644 --- a/core/tests/serializer_test.cc +++ b/core/tests/serializer_test.cc @@ -1,15 +1,14 @@ +#include + +#include +#include + #include "prometheus/counter.h" #include "prometheus/detail/future_std.h" #include "prometheus/family.h" #include "prometheus/text_serializer.h" - #include "raii_locale.h" -#include - -#include -#include - namespace prometheus { namespace { diff --git a/core/tests/summary_test.cc b/core/tests/summary_test.cc index 243a4dee..2efb4d7b 100644 --- a/core/tests/summary_test.cc +++ b/core/tests/summary_test.cc @@ -1,10 +1,10 @@ #include "prometheus/summary.h" +#include + #include #include -#include - namespace prometheus { namespace { diff --git a/core/tests/text_serializer_test.cc b/core/tests/text_serializer_test.cc index 3de00c19..bacd5345 100644 --- a/core/tests/text_serializer_test.cc +++ b/core/tests/text_serializer_test.cc @@ -77,7 +77,8 @@ TEST_F(TextSerializerTest, shouldSerializeTimestamp) { metric.timestamp_ms = 1234; const auto serialized = Serialize(MetricType::Counter); - EXPECT_THAT(serialized, testing::HasSubstr(name + " 64.00000000000000000 1234")); + EXPECT_THAT(serialized, + testing::HasSubstr(name + " 64.00000000000000000 1234")); } TEST_F(TextSerializerTest, shouldSerializeHistogramWithNoBuckets) { @@ -99,8 +100,8 @@ TEST_F(TextSerializerTest, shouldSerializeHistogram) { const auto serialized = Serialize(MetricType::Histogram); EXPECT_THAT(serialized, testing::HasSubstr(name + "_count 2")); EXPECT_THAT(serialized, testing::HasSubstr(name + "_sum 200.00000000000000")); - EXPECT_THAT(serialized, - testing::HasSubstr(name + "_bucket{le=\"1.00000000000000000\"} 1")); + EXPECT_THAT(serialized, testing::HasSubstr( + name + "_bucket{le=\"1.00000000000000000\"} 1")); EXPECT_THAT(serialized, testing::HasSubstr(name + "_bucket{le=\"+Inf\"} 2")); } @@ -113,8 +114,10 @@ TEST_F(TextSerializerTest, shouldSerializeSummary) { const auto serialized = Serialize(MetricType::Summary); EXPECT_THAT(serialized, testing::HasSubstr(name + "_count 2")); EXPECT_THAT(serialized, testing::HasSubstr(name + "_sum 200.00000000000000")); - EXPECT_THAT(serialized, - testing::HasSubstr(name + "{quantile=\"0.50000000000000000\"} 0.0000000000000000")); + EXPECT_THAT( + serialized, + testing::HasSubstr( + name + "{quantile=\"0.50000000000000000\"} 0.0000000000000000")); } } // namespace diff --git a/core/tests/utils_test.cc b/core/tests/utils_test.cc index a8933293..b1432e10 100644 --- a/core/tests/utils_test.cc +++ b/core/tests/utils_test.cc @@ -1,6 +1,7 @@ #include "prometheus/detail/utils.h" #include + #include namespace prometheus { diff --git a/push/tests/integration/sample_client.cc b/push/tests/integration/sample_client.cc index 84a6c79d..03414fe9 100644 --- a/push/tests/integration/sample_client.cc +++ b/push/tests/integration/sample_client.cc @@ -1,3 +1,7 @@ +#include +#include +#include + #include #include #include @@ -5,10 +9,6 @@ #include #include -#include -#include -#include - #ifdef _WIN32 #include #else From b15f3880bed333d673f467acc0f37ca5bfaaee6c Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Mon, 14 Dec 2020 20:06:52 +0100 Subject: [PATCH 124/206] chore: re-format with buildifier 3.5.0 --- bazel/civetweb.BUILD | 13 +++++++------ bazel/curl.BUILD | 19 +++++++++++-------- bazel/zlib.BUILD | 7 +++++-- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/bazel/civetweb.BUILD b/bazel/civetweb.BUILD index 52ef9130..6e5de4da 100644 --- a/bazel/civetweb.BUILD +++ b/bazel/civetweb.BUILD @@ -2,7 +2,8 @@ licenses(["notice"]) # MIT license config_setting( name = "darwin", - values = {"cpu": "darwin"},) + values = {"cpu": "darwin"}, +) config_setting( name = "darwin_x86_64", @@ -11,7 +12,7 @@ config_setting( config_setting( name = "windows", - values = { "cpu": "x64_windows" }, + values = {"cpu": "x64_windows"}, ) config_setting( @@ -66,9 +67,6 @@ cc_library( hdrs = [ "include/CivetServer.h", ], - deps = [ - ":libcivetweb", - ], copts = [ "-DUSE_IPV6", "-DNDEBUG", @@ -92,4 +90,7 @@ cc_library( "//conditions:default": ["-lrt"], }), visibility = ["//visibility:public"], -) \ No newline at end of file + deps = [ + ":libcivetweb", + ], +) diff --git a/bazel/curl.BUILD b/bazel/curl.BUILD index 38301b50..618462c1 100644 --- a/bazel/curl.BUILD +++ b/bazel/curl.BUILD @@ -18,18 +18,18 @@ licenses(["notice"]) # MIT/X derivative license load("@com_github_jupp0r_prometheus_cpp//bazel:curl.bzl", "CURL_COPTS") -package(features = ['no_copts_tokenization']) +package(features = ["no_copts_tokenization"]) config_setting( name = "windows", values = {"cpu": "x64_windows"}, - visibility = [ "//visibility:private" ], + visibility = ["//visibility:private"], ) config_setting( name = "osx", values = {"cpu": "darwin"}, - visibility = [ "//visibility:private" ], + visibility = ["//visibility:private"], ) cc_library( @@ -41,9 +41,15 @@ cc_library( "include/curl/*.h", "lib/**/*.h", ]), + copts = CURL_COPTS + [ + '-DOS="os"', + ], defines = ["CURL_STATICLIB"], - includes = ["include/", "lib/"], - linkopts = select({ + includes = [ + "include/", + "lib/", + ], + linkopts = select({ "//:windows": [ "-DEFAULTLIB:ws2_32.lib", "-DEFAULTLIB:advapi32.lib", @@ -54,8 +60,5 @@ cc_library( "-lpthread", ], }), - copts = CURL_COPTS + [ - '-DOS="os"', - ], visibility = ["//visibility:public"], ) diff --git a/bazel/zlib.BUILD b/bazel/zlib.BUILD index 9091e8eb..34cd232c 100644 --- a/bazel/zlib.BUILD +++ b/bazel/zlib.BUILD @@ -7,7 +7,10 @@ cc_library( srcs = glob(["*.c"]), hdrs = glob(["*.h"]), # Use -Dverbose=-1 to turn off zlib's trace logging. (bazelbuild/bazel#3280) - copts = ["-w", "-Dverbose=-1"], + copts = [ + "-w", + "-Dverbose=-1", + ], includes = ["."], visibility = ["//visibility:public"], -) \ No newline at end of file +) From 813a44477d271a2c1ae5bfc1c5318f2db114387a Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Mon, 14 Dec 2020 20:10:29 +0100 Subject: [PATCH 125/206] chore: remove extra block --- core/src/histogram.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/histogram.cc b/core/src/histogram.cc index 8445e231..86798534 100644 --- a/core/src/histogram.cc +++ b/core/src/histogram.cc @@ -36,7 +36,7 @@ void Histogram::ObserveMultiple(const std::vector& bucket_increments, sum_.Increment(sum_of_values); for (std::size_t i{0}; i < bucket_counts_.size(); ++i) { - { bucket_counts_[i].Increment(bucket_increments[i]); } + bucket_counts_[i].Increment(bucket_increments[i]); } } From fa49acc155b5b5eed29b903ea92a81d1a29ae403 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Mon, 14 Dec 2020 21:30:16 +0100 Subject: [PATCH 126/206] pull: Remove expired weak pointers to avoid leak --- pull/src/handler.cc | 12 ++++++++++++ pull/src/handler.h | 3 +++ 2 files changed, 15 insertions(+) diff --git a/pull/src/handler.cc b/pull/src/handler.cc index 69e6d9d1..49d8a68e 100644 --- a/pull/src/handler.cc +++ b/pull/src/handler.cc @@ -1,5 +1,6 @@ #include "handler.h" +#include #include #include "prometheus/counter.h" @@ -116,6 +117,7 @@ static std::size_t WriteResponse(struct mg_connection* conn, void MetricsHandler::RegisterCollectable( const std::weak_ptr& collectable) { std::lock_guard lock{collectables_mutex_}; + CleanupStalePointers(collectables_); collectables_.push_back(collectable); } @@ -142,5 +144,15 @@ bool MetricsHandler::handleGet(CivetServer*, struct mg_connection* conn) { num_scrapes_.Increment(); return true; } + +void MetricsHandler::CleanupStalePointers( + std::vector>& collectables) { + collectables.erase( + std::remove_if(std::begin(collectables), std::end(collectables), + [](const std::weak_ptr& candidate) { + return candidate.expired(); + }), + std::end(collectables)); +} } // namespace detail } // namespace prometheus diff --git a/pull/src/handler.h b/pull/src/handler.h index 79ddc4a9..923cc525 100644 --- a/pull/src/handler.h +++ b/pull/src/handler.h @@ -20,6 +20,9 @@ class MetricsHandler : public CivetHandler { bool handleGet(CivetServer* server, struct mg_connection* conn) override; private: + static void CleanupStalePointers( + std::vector>& collectables); + std::mutex collectables_mutex_; std::vector> collectables_; Family& bytes_transferred_family_; From c71ae77cf395ff5ee449e636c0687a9ced37b279 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Mon, 14 Dec 2020 21:58:51 +0100 Subject: [PATCH 127/206] push: Remove expired weak pointers to avoid leak --- push/include/prometheus/gateway.h | 2 ++ push/src/gateway.cc | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/push/include/prometheus/gateway.h b/push/include/prometheus/gateway.h index a7a6e1d9..49f081c5 100644 --- a/push/include/prometheus/gateway.h +++ b/push/include/prometheus/gateway.h @@ -68,6 +68,8 @@ class PROMETHEUS_CPP_PUSH_EXPORT Gateway { int push(HttpMethod method); std::future async_push(HttpMethod method); + + static void CleanupStalePointers(std::vector& collectables); }; } // namespace prometheus diff --git a/push/src/gateway.cc b/push/src/gateway.cc index d672a331..41c0f2f5 100644 --- a/push/src/gateway.cc +++ b/push/src/gateway.cc @@ -73,6 +73,7 @@ void Gateway::RegisterCollectable(const std::weak_ptr& collectable, } } + CleanupStalePointers(collectables_); collectables_.push_back(std::make_pair(collectable, ss.str())); } @@ -216,4 +217,14 @@ std::future Gateway::AsyncDelete() { return std::async(std::launch::async, [&] { return Delete(); }); } +void Gateway::CleanupStalePointers( + std::vector& collectables) { + collectables.erase( + std::remove_if(std::begin(collectables), std::end(collectables), + [](const CollectableEntry& candidate) { + return candidate.first.expired(); + }), + std::end(collectables)); +} + } // namespace prometheus From 9638191bc94aa187e72ef780186c7c64a8525f3c Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Mon, 14 Dec 2020 22:13:39 +0100 Subject: [PATCH 128/206] pull: Add integration test for exposer --- pull/src/handler.cc | 2 +- pull/tests/integration/BUILD.bazel | 12 ++ pull/tests/integration/CMakeLists.txt | 20 ++++ pull/tests/integration/integration_test.cc | 126 +++++++++++++++++++++ 4 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 pull/tests/integration/integration_test.cc diff --git a/pull/src/handler.cc b/pull/src/handler.cc index 49d8a68e..094eb07d 100644 --- a/pull/src/handler.cc +++ b/pull/src/handler.cc @@ -146,7 +146,7 @@ bool MetricsHandler::handleGet(CivetServer*, struct mg_connection* conn) { } void MetricsHandler::CleanupStalePointers( - std::vector>& collectables) { + std::vector>& collectables) { collectables.erase( std::remove_if(std::begin(collectables), std::end(collectables), [](const std::weak_ptr& candidate) { diff --git a/pull/tests/integration/BUILD.bazel b/pull/tests/integration/BUILD.bazel index 441dd25c..283679d6 100644 --- a/pull/tests/integration/BUILD.bazel +++ b/pull/tests/integration/BUILD.bazel @@ -36,3 +36,15 @@ sh_test( ], tags = ["manual"], ) + +cc_test( + name = "integration_test", + srcs = ["integration_test.cc"], + copts = ["-Iexternal/googletest/include"], + linkstatic = True, + deps = [ + "//pull", + "@com_github_curl//:curl", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/pull/tests/integration/CMakeLists.txt b/pull/tests/integration/CMakeLists.txt index 74ed5bf1..4478d92e 100644 --- a/pull/tests/integration/CMakeLists.txt +++ b/pull/tests/integration/CMakeLists.txt @@ -25,3 +25,23 @@ target_link_libraries(sample_server_auth PRIVATE ${PROJECT_NAME}::pull ) + +find_package(CURL) + +if(CURL_FOUND) + add_executable(prometheus_pull_integration_test + integration_test.cc + ) + + target_link_libraries(prometheus_pull_integration_test + PRIVATE + ${PROJECT_NAME}::pull + CURL::libcurl + GTest::gmock_main + ) + + add_test( + NAME prometheus_pull_integration_test + COMMAND prometheus_pull_integration_test + ) +endif() diff --git a/pull/tests/integration/integration_test.cc b/pull/tests/integration/integration_test.cc new file mode 100644 index 00000000..a0138d32 --- /dev/null +++ b/pull/tests/integration/integration_test.cc @@ -0,0 +1,126 @@ +#include +#include + +#include +#include + +#include "prometheus/counter.h" +#include "prometheus/detail/future_std.h" +#include "prometheus/exposer.h" +#include "prometheus/registry.h" + +namespace prometheus { +namespace { + +using namespace testing; + +class IntegrationTest : public testing::Test { + public: + void SetUp() override { + exposer_ = detail::make_unique("127.0.0.1:0"); + auto ports = exposer_->GetListeningPorts(); + base_url_ = std::string("http://127.0.0.1:") + std::to_string(ports.at(0)); + } + + struct Resonse { + long code = 0; + std::string body; + }; + + Resonse FetchMetrics(std::string metrics_path) { + auto curl = std::shared_ptr(curl_easy_init(), curl_easy_cleanup); + if (!curl) { + throw std::runtime_error("failed to initialize libcurl"); + } + + const auto url = base_url_ + metrics_path; + Resonse response; + + curl_easy_setopt(curl.get(), CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &response.body); + curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, WriteCallback); + + CURLcode curl_error = curl_easy_perform(curl.get()); + if (curl_error != CURLE_OK) { + throw std::runtime_error("failed to perform HTTP request"); + } + + curl_easy_getinfo(curl.get(), CURLINFO_RESPONSE_CODE, &response.code); + + return response; + } + + std::shared_ptr RegisterSomeCounter(const std::string& name, + const std::string& path) { + const auto registry = std::make_shared(); + + BuildCounter().Name(name).Register(*registry).Add({}).Increment(); + + exposer_->RegisterCollectable(registry, path); + + return registry; + }; + + std::unique_ptr exposer_; + + std::string base_url_; + std::string default_metrics_path_ = "/metrics"; + + private: + static size_t WriteCallback(void* contents, size_t size, size_t nmemb, + void* userp) { + auto response = reinterpret_cast(userp); + + size_t realsize = size * nmemb; + response->append(reinterpret_cast(contents), realsize); + return realsize; + } +}; + +TEST_F(IntegrationTest, doesNotExposeAnythingOnDefaultPath) { + const auto metrics = FetchMetrics(default_metrics_path_); + + EXPECT_GE(metrics.code, 400); +} + +TEST_F(IntegrationTest, exposeSingleCounter) { + const std::string counter_name = "example_total"; + auto registry = RegisterSomeCounter(counter_name, default_metrics_path_); + + const auto metrics = FetchMetrics(default_metrics_path_); + + ASSERT_EQ(metrics.code, 200); + EXPECT_THAT(metrics.body, HasSubstr(counter_name)); +} + +TEST_F(IntegrationTest, exposesCountersOnDifferentUrls) { + const std::string first_metrics_path = "/first"; + const std::string second_metrics_path = "/second"; + + const std::string first_counter_name = "first_total"; + const std::string second_counter_name = "second_total"; + + const auto first_registry = + RegisterSomeCounter(first_counter_name, first_metrics_path); + const auto second_registry = + RegisterSomeCounter(second_counter_name, second_metrics_path); + + // all set-up + + const auto first_metrics = FetchMetrics(first_metrics_path); + const auto second_metrics = FetchMetrics(second_metrics_path); + + // check results + + ASSERT_EQ(first_metrics.code, 200); + ASSERT_EQ(second_metrics.code, 200); + + EXPECT_THAT(first_metrics.body, HasSubstr(first_counter_name)); + EXPECT_THAT(second_metrics.body, HasSubstr(second_counter_name)); + + EXPECT_THAT(first_metrics.body, Not(HasSubstr(second_counter_name))); + EXPECT_THAT(second_metrics.body, Not(HasSubstr(first_counter_name))); +} + +} // namespace +} // namespace prometheus From 87f93a1e38f4c9bc41d33bc4a4c932ef34ad40de Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Wed, 16 Dec 2020 21:18:43 +0100 Subject: [PATCH 129/206] pull: Work-around assertion and race-condition in auth handler --- pull/src/endpoint.cc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/pull/src/endpoint.cc b/pull/src/endpoint.cc index 274e17c5..da4125cf 100644 --- a/pull/src/endpoint.cc +++ b/pull/src/endpoint.cc @@ -19,7 +19,10 @@ Endpoint::Endpoint(CivetServer& server, std::string uri) Endpoint::~Endpoint() { server_.removeHandler(uri_); - server_.removeAuthHandler(uri_); + if (auth_handler_) { + // work-around https://github.com/civetweb/civetweb/issues/941 + server_.removeAuthHandler(uri_); + } } void Endpoint::RegisterCollectable( @@ -30,9 +33,12 @@ void Endpoint::RegisterCollectable( void Endpoint::RegisterAuth( std::function authCB, const std::string& realm) { - auth_handler_ = + // split creating, assigning, and storing to avoid a race-condition when + // being called the second time and the handler is replaced + auto new_handler = detail::make_unique(std::move(authCB), realm); - server_.addAuthHandler(uri_, auth_handler_.get()); + server_.addAuthHandler(uri_, new_handler.get()); + auth_handler_ = std::move(new_handler); } const std::string& Endpoint::GetURI() const { return uri_; } From bd887dafbdc94a1313cdcb9e70fbc9ab8f9c8789 Mon Sep 17 00:00:00 2001 From: "Mark Klein (mklein201)" Date: Tue, 17 Nov 2020 13:25:53 -0800 Subject: [PATCH 130/206] pull: Add RemoveCollectable Closes: #415 --- pull/include/prometheus/exposer.h | 3 +++ pull/src/endpoint.cc | 5 +++++ pull/src/endpoint.h | 1 + pull/src/exposer.cc | 6 ++++++ pull/src/handler.cc | 14 ++++++++++++++ pull/src/handler.h | 1 + pull/tests/integration/integration_test.cc | 12 ++++++++++++ 7 files changed, 42 insertions(+) diff --git a/pull/include/prometheus/exposer.h b/pull/include/prometheus/exposer.h index 1f3b0775..e6ceb85f 100644 --- a/pull/include/prometheus/exposer.h +++ b/pull/include/prometheus/exposer.h @@ -33,6 +33,9 @@ class PROMETHEUS_CPP_PULL_EXPORT Exposer { const std::string& realm = "Prometheus-cpp Exporter", const std::string& uri = std::string("/metrics")); + void RemoveCollectable(const std::weak_ptr& collectable, + const std::string& uri = std::string("/metrics")); + std::vector GetListeningPorts() const; private: diff --git a/pull/src/endpoint.cc b/pull/src/endpoint.cc index da4125cf..0e9f746f 100644 --- a/pull/src/endpoint.cc +++ b/pull/src/endpoint.cc @@ -41,6 +41,11 @@ void Endpoint::RegisterAuth( auth_handler_ = std::move(new_handler); } +void Endpoint::RemoveCollectable( + const std::weak_ptr& collectable) { + metrics_handler_->RemoveCollectable(collectable); +} + const std::string& Endpoint::GetURI() const { return uri_; } } // namespace detail diff --git a/pull/src/endpoint.h b/pull/src/endpoint.h index af64d5f8..2a58d847 100644 --- a/pull/src/endpoint.h +++ b/pull/src/endpoint.h @@ -24,6 +24,7 @@ class Endpoint { void RegisterAuth( std::function authCB, const std::string& realm); + void RemoveCollectable(const std::weak_ptr& collectable); const std::string& GetURI() const; diff --git a/pull/src/exposer.cc b/pull/src/exposer.cc index 4326c349..b61737c0 100644 --- a/pull/src/exposer.cc +++ b/pull/src/exposer.cc @@ -35,6 +35,12 @@ void Exposer::RegisterAuth( endpoint.RegisterAuth(std::move(authCB), realm); } +void Exposer::RemoveCollectable(const std::weak_ptr& collectable, + const std::string& uri) { + auto& endpoint = GetEndpointForUri(uri); + endpoint.RemoveCollectable(collectable); +} + std::vector Exposer::GetListeningPorts() const { return server_->getListeningPorts(); } diff --git a/pull/src/handler.cc b/pull/src/handler.cc index 094eb07d..20a552a0 100644 --- a/pull/src/handler.cc +++ b/pull/src/handler.cc @@ -121,6 +121,20 @@ void MetricsHandler::RegisterCollectable( collectables_.push_back(collectable); } +void MetricsHandler::RemoveCollectable( + const std::weak_ptr& collectable) { + std::lock_guard lock{collectables_mutex_}; + + auto locked = collectable.lock(); + auto same_pointer = [&locked](const std::weak_ptr& candidate) { + return locked == candidate.lock(); + }; + + collectables_.erase(std::remove_if(std::begin(collectables_), + std::end(collectables_), same_pointer), + std::end(collectables_)); +} + bool MetricsHandler::handleGet(CivetServer*, struct mg_connection* conn) { auto start_time_of_request = std::chrono::steady_clock::now(); diff --git a/pull/src/handler.h b/pull/src/handler.h index 923cc525..017e2a7e 100644 --- a/pull/src/handler.h +++ b/pull/src/handler.h @@ -16,6 +16,7 @@ class MetricsHandler : public CivetHandler { explicit MetricsHandler(Registry& registry); void RegisterCollectable(const std::weak_ptr& collectable); + void RemoveCollectable(const std::weak_ptr& collectable); bool handleGet(CivetServer* server, struct mg_connection* conn) override; diff --git a/pull/tests/integration/integration_test.cc b/pull/tests/integration/integration_test.cc index a0138d32..c7fe6b55 100644 --- a/pull/tests/integration/integration_test.cc +++ b/pull/tests/integration/integration_test.cc @@ -122,5 +122,17 @@ TEST_F(IntegrationTest, exposesCountersOnDifferentUrls) { EXPECT_THAT(second_metrics.body, Not(HasSubstr(first_counter_name))); } +TEST_F(IntegrationTest, unexposeRegistry) { + const std::string counter_name = "some_counter_total"; + const auto registry = + RegisterSomeCounter(counter_name, default_metrics_path_); + + exposer_->RemoveCollectable(registry, default_metrics_path_); + + const auto metrics = FetchMetrics(default_metrics_path_); + ASSERT_EQ(metrics.code, 200); + EXPECT_THAT(metrics.body, Not(HasSubstr(counter_name))); +} + } // namespace } // namespace prometheus From b128da64591efd58a8b13abd182f1c5cd9c4791a Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 17 Dec 2020 19:31:03 +0100 Subject: [PATCH 131/206] chore: Raise version to v0.12.0 due to changed public interface --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d7759775..ebb94353 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ if(POLICY CMP0091) cmake_policy(SET CMP0091 NEW) # recognize CMAKE_MSVC_RUNTIME_LIBRARY endif() -project(prometheus-cpp VERSION 0.11.0) +project(prometheus-cpp VERSION 0.12.0) include(GenerateExportHeader) include(GNUInstallDirs) From eb06094dee7a47838d458818d2986ebda8474b5f Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Wed, 23 Dec 2020 11:52:03 +0100 Subject: [PATCH 132/206] ci: Run bazel from separate workflow --- .github/scripts/run-bazel-test | 19 -------- .github/scripts/run-bazel-test.cmd | 5 -- .github/scripts/run-prepare | 10 ---- .github/workflows/bazel-ci.yml | 47 +++++++++++++++++++ .../continuous-integration-workflow.yml | 2 +- .gitignore | 2 +- 6 files changed, 49 insertions(+), 36 deletions(-) delete mode 100755 .github/scripts/run-bazel-test delete mode 100644 .github/scripts/run-bazel-test.cmd create mode 100644 .github/workflows/bazel-ci.yml diff --git a/.github/scripts/run-bazel-test b/.github/scripts/run-bazel-test deleted file mode 100755 index 48261b95..00000000 --- a/.github/scripts/run-bazel-test +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -WORKSPACE=$(cd "$(dirname "${BASH_SOURCE[0]}")"/../.. && /bin/pwd -P) - -OS_ARG=${1:?} - -bazel build //... - -bazel test --test_output=all //core/... //pull/... -bazel test --test_output=all //pull/tests/integration:scrape-test - -#if [[ "${OS_ARG}" == "macOS"* ]] -#then -# bazel test --test_output=all //pull/tests/integration:lint-test -#fi - -bazel run -c opt //core/benchmarks diff --git a/.github/scripts/run-bazel-test.cmd b/.github/scripts/run-bazel-test.cmd deleted file mode 100644 index 1055c1c7..00000000 --- a/.github/scripts/run-bazel-test.cmd +++ /dev/null @@ -1,5 +0,0 @@ -bazel build //... || EXIT /B 1 - -bazel test --test_output=all //core/... //pull/... || EXIT /B 1 - -bazel run -c opt //core/benchmarks || EXIT /B 1 diff --git a/.github/scripts/run-prepare b/.github/scripts/run-prepare index 0fbe1045..e80d1276 100755 --- a/.github/scripts/run-prepare +++ b/.github/scripts/run-prepare @@ -15,21 +15,11 @@ case "${OS_ARG}" in ;; esac - curl -sL https://repos.influxdata.com/influxdb.key | sudo apt-key add - - source /etc/lsb-release - echo "deb https://repos.influxdata.com/${DISTRIB_ID,,} ${DISTRIB_CODENAME} stable" | sudo tee /etc/apt/sources.list.d/influxdb.list - packages+=(telegraf) - sudo apt-get remove -y --purge man-db # avoid time-consuming trigger sudo apt-get update sudo apt-get install -y "${packages[@]}" sudo locale-gen de_DE.UTF-8 # used by SerializerTest ;; - - macOS*) - packages=(prometheus telegraf) - brew install "${packages[@]}" - ;; esac case "${BUILDSYSTEM_ARG}" in diff --git a/.github/workflows/bazel-ci.yml b/.github/workflows/bazel-ci.yml new file mode 100644 index 00000000..841d9b3a --- /dev/null +++ b/.github/workflows/bazel-ci.yml @@ -0,0 +1,47 @@ +name: Bazel CI +on: [push, pull_request] + +jobs: + build: + name: Bazel on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [macos-latest, ubuntu-20.04, windows-2019] + steps: + - name: Checkout source + uses: actions/checkout@v2 + + - name: Generate German locale on Ubuntu + if: runner.os == 'Linux' + run: | + sudo apt-get remove -y --purge man-db # avoid time-consuming trigger + sudo apt-get update + sudo apt-get install -y locales + sudo locale-gen de_DE.UTF-8 # used by SerializerTest + + - name: Install telegraf on Ubuntu + if: runner.os == 'Linux' + run: | + curl -sL https://repos.influxdata.com/influxdb.key | sudo apt-key add - + source /etc/lsb-release + echo "deb https://repos.influxdata.com/${DISTRIB_ID,,} ${DISTRIB_CODENAME} stable" | sudo tee /etc/apt/sources.list.d/influxdb.list + sudo apt-get update + sudo apt-get install -y telegraf + + - name: Install telegraf on macOS + if: runner.os == 'macOS' + run: brew install telegraf + + - name: Build + run: bazel build //... + + - name: Test + run: bazel test --test_output=all //core/... //pull/... + + - name: Scraping Test + if: runner.os != 'Windows' + run: bazel test --test_output=all //pull/tests/integration:scrape-test + + - name: Benchmark + run: bazel run -c opt //core/benchmarks diff --git a/.github/workflows/continuous-integration-workflow.yml b/.github/workflows/continuous-integration-workflow.yml index 3809bf74..76a4a202 100644 --- a/.github/workflows/continuous-integration-workflow.yml +++ b/.github/workflows/continuous-integration-workflow.yml @@ -7,7 +7,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - buildsystem: [bazel, cmake] + buildsystem: [cmake] os: [macOS-latest, ubuntu-16.04, windows-2016] steps: - uses: actions/checkout@v2 diff --git a/.gitignore b/.gitignore index 3406309c..5267e3b8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -bazel-* +/bazel-* cmake-build-*/ _*/ .idea/ From caaf89005ff672e393cabcb2636a0d9ec4eb5bb5 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 24 Dec 2020 00:21:09 +0100 Subject: [PATCH 133/206] ci: Make CMake workflow more fine-grained --- .github/scripts/run-cmake-test | 31 ----- .github/scripts/run-cmake-test.cmd | 17 --- .github/scripts/run-prepare.cmd | 4 - .github/workflows/cmake-ci.yml | 109 ++++++++++++++++++ .../continuous-integration-workflow.yml | 23 ---- 5 files changed, 109 insertions(+), 75 deletions(-) delete mode 100755 .github/scripts/run-cmake-test delete mode 100644 .github/scripts/run-cmake-test.cmd delete mode 100644 .github/scripts/run-prepare.cmd create mode 100644 .github/workflows/cmake-ci.yml delete mode 100644 .github/workflows/continuous-integration-workflow.yml diff --git a/.github/scripts/run-cmake-test b/.github/scripts/run-cmake-test deleted file mode 100755 index d5cae35e..00000000 --- a/.github/scripts/run-cmake-test +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -WORKSPACE=$(cd "$(dirname "${BASH_SOURCE[0]}")"/../.. && /bin/pwd -P) - -# Build with internal dependencies - -mkdir "${WORKSPACE}/_build_internal_deps" && cd $_ -cmake -DUSE_THIRDPARTY_LIBRARIES=ON -DENABLE_WARNINGS_AS_ERRORS=ON -DENABLE_COMPRESSION=OFF -DENABLE_PUSH=OFF "${WORKSPACE}" -make -j$(getconf _NPROCESSORS_ONLN) -ctest -V -mkdir -p deploy -make DESTDIR="${PWD}/deploy" install - -mkdir "${WORKSPACE}/_import_internal_deps" && cd $_ -cmake "-Dprometheus-cpp_DIR=${WORKSPACE}/_build_internal_deps/deploy/usr/local/lib/cmake/prometheus-cpp" "${WORKSPACE}/cmake/project-import" -make -j$(getconf _NPROCESSORS_ONLN) - -# Build with external dependencies - -mkdir "${WORKSPACE}/_build" && cd $_ -cmake -DUSE_THIRDPARTY_LIBRARIES=OFF "-DCMAKE_TOOLCHAIN_FILE=${VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake" "${WORKSPACE}" -make -j$(getconf _NPROCESSORS_ONLN) -ctest -V -LE Benchmark -mkdir -p deploy -make DESTDIR="${PWD}/deploy" install - -mkdir "${WORKSPACE}/_import" && cd $_ -cmake "-DCMAKE_TOOLCHAIN_FILE=${VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake" "-Dprometheus-cpp_DIR=${WORKSPACE}/_build/deploy/usr/local/lib/cmake/prometheus-cpp" "${WORKSPACE}/cmake/project-import" -make -j$(getconf _NPROCESSORS_ONLN) diff --git a/.github/scripts/run-cmake-test.cmd b/.github/scripts/run-cmake-test.cmd deleted file mode 100644 index 86b8a67f..00000000 --- a/.github/scripts/run-cmake-test.cmd +++ /dev/null @@ -1,17 +0,0 @@ -mkdir "_build_internal_deps" || EXIT /B 1 -cd "_build_internal_deps" || EXIT /B 1 -cmake .. -DUSE_THIRDPARTY_LIBRARIES=ON -DENABLE_WARNINGS_AS_ERRORS=ON -DENABLE_COMPRESSION=OFF -DENABLE_PUSH=OFF || EXIT /B 1 -cmake --build . --config Debug || EXIT /B 1 -cmake --build . --config Release || EXIT /B 1 -ctest -C Debug -V -LE Benchmark || EXIT /B 1 -ctest -C Release -V || EXIT /B 1 -cd .. || EXIT /B 1 - -mkdir "_build" || EXIT /B 1 -cd "_build" || EXIT /B 1 -cmake .. -DUSE_THIRDPARTY_LIBRARIES=OFF -DCMAKE_TOOLCHAIN_FILE=%VCPKG_INSTALLATION_ROOT%\scripts\buildsystems\vcpkg.cmake || EXIT /B 1 -cmake --build . --config Debug || EXIT /B 1 -cmake --build . --config Release || EXIT /B 1 -ctest -C Debug -V -LE Benchmark || EXIT /B 1 -ctest -C Release -V || EXIT /B 1 -cd .. || EXIT /B 1 diff --git a/.github/scripts/run-prepare.cmd b/.github/scripts/run-prepare.cmd deleted file mode 100644 index ec14d92f..00000000 --- a/.github/scripts/run-prepare.cmd +++ /dev/null @@ -1,4 +0,0 @@ -if [%1] == [cmake] ( - %VCPKG_INSTALLATION_ROOT%/vcpkg install benchmark civetweb curl gtest zlib || EXIT /B 1 -) - diff --git a/.github/workflows/cmake-ci.yml b/.github/workflows/cmake-ci.yml new file mode 100644 index 00000000..4e5fca9c --- /dev/null +++ b/.github/workflows/cmake-ci.yml @@ -0,0 +1,109 @@ +name: CMake CI +on: [push, pull_request] + +jobs: + build: + name: CMake on ${{ matrix.os }} with ${{ matrix.dependencies }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [macOS-latest, ubuntu-18.04, windows-2016] + dependencies: [submodule, vcpkg] + steps: + - name: Checkout source + uses: actions/checkout@v2 + + - name: Checkout submodules + if: matrix.dependencies == 'submodule' + shell: bash + run: | + auth_header="$(git config --local --get http.https://github.com/.extraheader)" + git submodule sync --recursive + git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1 + + - name: Mount vcpkg cache + if: matrix.dependencies == 'vcpkg' + uses: actions/cache@v2 + with: + path: "~/.cache/vcpkg/archives" + key: vcpkg-${{ runner.os }} + + - name: install vcpkg dependencies + if: matrix.dependencies == 'vcpkg' + run: vcpkg install benchmark civetweb curl[core] gtest zlib + + - name: Generate German locale on Ubuntu + if: runner.os == 'Linux' + run: | + sudo apt-get remove -y --purge man-db # avoid time-consuming trigger + sudo apt-get update + sudo apt-get install -y locales + sudo locale-gen de_DE.UTF-8 # used by SerializerTest + + - name: install ninja on Ubuntu + if: runner.os == 'Linux' + run: | + sudo apt-get install -y ninja-build + + - name: install ninja on macOS + if: runner.os == 'macOS' + run: brew install ninja + + - name: "Configure for Unix with internal dependencies" + if: matrix.dependencies == 'submodule' && runner.os != 'Windows' + run: cmake -DUSE_THIRDPARTY_LIBRARIES=ON -DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/_install -DENABLE_WARNINGS_AS_ERRORS=ON -DENABLE_COMPRESSION=OFF -DENABLE_PUSH=OFF -DCMAKE_DEBUG_POSTFIX=_d -DCMAKE_CONFIGURATION_TYPES='Release;Debug' -G"Ninja Multi-Config" -S ${{ github.workspace }} -B ${{ github.workspace }}/_build + + - name: "Configure for Windows with internal dependencies" + if: matrix.dependencies == 'submodule' && runner.os == 'Windows' + run: cmake -DUSE_THIRDPARTY_LIBRARIES=ON -DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/_install -DENABLE_WARNINGS_AS_ERRORS=ON -DENABLE_COMPRESSION=OFF -DENABLE_PUSH=OFF -DCMAKE_DEBUG_POSTFIX=_d -S ${{ github.workspace }} -B ${{ github.workspace }}/_build + + - name: "Configure for Unix with vcpkg dependencies" + if: matrix.dependencies == 'vcpkg' && runner.os != 'Windows' + run: cmake -DUSE_THIRDPARTY_LIBRARIES=OFF -DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/_install "-DCMAKE_TOOLCHAIN_FILE=${VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake" -DCMAKE_DEBUG_POSTFIX=_d -DCMAKE_CONFIGURATION_TYPES='Release;Debug' -G"Ninja Multi-Config" -S ${{ github.workspace }} -B ${{ github.workspace }}/_build + + - name: "Configure for Windows with vcpkg dependencies" + if: matrix.dependencies == 'vcpkg' && runner.os == 'Windows' + run: cmake -DUSE_THIRDPARTY_LIBRARIES=OFF -DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/_install "-DCMAKE_TOOLCHAIN_FILE=${Env:VCPKG_INSTALLATION_ROOT}\scripts\buildsystems\vcpkg.cmake" -DCMAKE_DEBUG_POSTFIX=_d -S ${{ github.workspace }} -B ${{ github.workspace }}/_build + + - name: "Build Debug" + run: cmake --build ${{ github.workspace }}/_build --config Debug + + - name: "Build Release" + run: cmake --build ${{ github.workspace }}/_build --config Release + + - name: "Test Debug" + run: ctest -C Debug -V -LE Benchmark + working-directory: "${{ github.workspace }}/_build" + + - name: "Test Release" + run: ctest -C Debug -V -LE Benchmark + working-directory: "${{ github.workspace }}/_build" + + - name: "Install Debug" + run: cmake --install ${{ github.workspace }}/_build --config Debug + + - name: "Install Release" + run: cmake --install ${{ github.workspace }}/_build --config Release + + - name: "Configure import for Unix with internal dependencies" + if: matrix.dependencies == 'submodule' && runner.os != 'Windows' + run: cmake -Dprometheus-cpp_DIR=${{ github.workspace }}/_install/lib/cmake/prometheus-cpp -DCMAKE_CONFIGURATION_TYPES='Release;Debug' -G"Ninja Multi-Config" -S ${{ github.workspace }}/cmake/project-import -B ${{ github.workspace }}/_import + + - name: "Configure import for Windows with internal dependencies" + if: matrix.dependencies == 'submodule' && runner.os == 'Windows' + run: cmake -Dprometheus-cpp_DIR=${{ github.workspace }}/_install/lib/cmake/prometheus-cpp -S ${{ github.workspace }}/cmake/project-import -B ${{ github.workspace }}/_import + + - name: "Configure import for Unix with vcpkg dependencies" + if: matrix.dependencies == 'vcpkg' && runner.os != 'Windows' + run: cmake -Dprometheus-cpp_DIR=${{ github.workspace }}/_install/lib/cmake/prometheus-cpp "-DCMAKE_TOOLCHAIN_FILE=${VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake" -DCMAKE_CONFIGURATION_TYPES='Release;Debug' -G"Ninja Multi-Config" -S ${{ github.workspace }}/cmake/project-import -B ${{ github.workspace }}/_import + + - name: "Configure import for Windows with vcpkg dependencies" + if: matrix.dependencies == 'vcpkg' && runner.os == 'Windows' + run: cmake -Dprometheus-cpp_DIR=${{ github.workspace }}/_install/lib/cmake/prometheus-cpp "-DCMAKE_TOOLCHAIN_FILE=${Env:VCPKG_INSTALLATION_ROOT}\scripts\buildsystems\vcpkg.cmake" -S ${{ github.workspace }}/cmake/project-import -B ${{ github.workspace }}/_import + + - name: "Build import Debug" + run: cmake --build ${{ github.workspace }}/_import --config Debug + + - name: "Build import Release" + run: cmake --build ${{ github.workspace }}/_import --config Release diff --git a/.github/workflows/continuous-integration-workflow.yml b/.github/workflows/continuous-integration-workflow.yml deleted file mode 100644 index 76a4a202..00000000 --- a/.github/workflows/continuous-integration-workflow.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Continuous Integration -on: [push, pull_request] - -jobs: - build: - name: ${{ matrix.buildsystem }} on ${{ matrix.os }} - runs-on: ${{ matrix.os }} - strategy: - matrix: - buildsystem: [cmake] - os: [macOS-latest, ubuntu-16.04, windows-2016] - steps: - - uses: actions/checkout@v2 - - name: Checkout submodules - shell: bash - run: | - auth_header="$(git config --local --get http.https://github.com/.extraheader)" - git submodule sync --recursive - git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1 - - name: Prepare - run: .github/scripts/run-prepare ${{ matrix.buildsystem }} ${{ matrix.os }} - - name: Test - run: .github/scripts/run-${{ matrix.buildsystem }}-test ${{ matrix.os }} From fda05ed105d59e3863d97d0ec816cc320028839d Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 26 Dec 2020 15:30:24 +0100 Subject: [PATCH 134/206] pull: Add better example Closes: #423 --- README.md | 66 ++++++++++++++++++------- pull/tests/integration/sample_server.cc | 55 +++++++++++++++------ pull/tests/integration/scrape.sh | 2 +- 3 files changed, 89 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 7a14aa0e..cd289c95 100644 --- a/README.md +++ b/README.md @@ -18,48 +18,76 @@ other push/pull collections can be added as plugins. See https://jupp0r.github.io/prometheus-cpp for more detailed interface documentation. ``` c++ +#include +#include +#include + +#include #include -#include +#include #include #include #include -#include -#include -#include - -int main(int argc, char** argv) { +int main() { using namespace prometheus; // create an http server running on port 8080 Exposer exposer{"127.0.0.1:8080"}; - // create a metrics registry with component=main labels applied to all its - // metrics + // create a metrics registry + // @note it's the users responsibility to keep the object alive auto registry = std::make_shared(); // add a new counter family to the registry (families combine values with the // same name, but distinct label dimensions) - auto& counter_family = BuildCounter() - .Name("time_running_seconds_total") - .Help("How many seconds is this server running?") - .Labels({{"label", "value"}}) + // + // @note please follow the metric-naming best-practices: + // https://prometheus.io/docs/practices/naming/ + auto& packet_counter = BuildCounter() + .Name("observed_packets_total") + .Help("Number of observed packets") .Register(*registry); - // add a counter to the metric family - auto& second_counter = counter_family.Add( - {{"another_label", "value"}, {"yet_another_label", "value"}}); - - // ask the exposer to scrape the registry on incoming scrapes + // add and remember dimensional data, incrementing those is very cheap + auto& tcp_rx_counter = + packet_counter.Add({{"protocol", "tcp"}, {"direction", "rx"}}); + auto& tcp_tx_counter = + packet_counter.Add({{"protocol", "tcp"}, {"direction", "tx"}}); + auto& udp_rx_counter = + packet_counter.Add({{"protocol", "udp"}, {"direction", "rx"}}); + auto& udp_tx_counter = + packet_counter.Add({{"protocol", "udp"}, {"direction", "tx"}}); + + // add a counter whose dimensional data is not known at compile time + // nevertheless dimensional values should only occur in low cardinality: + // https://prometheus.io/docs/practices/naming/#labels + auto& http_requests_counter = BuildCounter() + .Name("http_requests_total") + .Help("Number of HTTP requests") + .Register(*registry); + + // ask the exposer to scrape the registry on incoming HTTP requests exposer.RegisterCollectable(registry); for (;;) { std::this_thread::sleep_for(std::chrono::seconds(1)); - // increment the counter by one (second) - second_counter.Increment(); + const auto random_value = std::rand(); + + if (random_value & 1) tcp_rx_counter.Increment(); + if (random_value & 2) tcp_tx_counter.Increment(); + if (random_value & 4) udp_rx_counter.Increment(); + if (random_value & 8) udp_tx_counter.Increment(); + + const std::array methods = {"GET", "PUT", "POST", "HEAD"}; + auto method = methods.at(random_value % methods.size()); + // dynamically calling Family.Add() works but is slow and should be + // avoided + http_requests_counter.Add({{"method", method}}).Increment(); } return 0; } + ``` ## Requirements diff --git a/pull/tests/integration/sample_server.cc b/pull/tests/integration/sample_server.cc index 72512fa2..55ce0163 100644 --- a/pull/tests/integration/sample_server.cc +++ b/pull/tests/integration/sample_server.cc @@ -2,8 +2,9 @@ #include #include +#include #include -#include +#include #include #include #include @@ -12,31 +13,57 @@ int main() { using namespace prometheus; // create an http server running on port 8080 - Exposer exposer{"127.0.0.1:8080", 1}; + Exposer exposer{"127.0.0.1:8080"}; - // create a metrics registry with component=main labels applied to all its - // metrics + // create a metrics registry + // @note it's the users responsibility to keep the object alive auto registry = std::make_shared(); // add a new counter family to the registry (families combine values with the // same name, but distinct label dimensions) - auto& counter_family = BuildCounter() - .Name("time_running_seconds_total") - .Help("How many seconds is this server running?") - .Labels({{"label", "value"}}) + // + // @note please follow the metric-naming best-practices: + // https://prometheus.io/docs/practices/naming/ + auto& packet_counter = BuildCounter() + .Name("observed_packets_total") + .Help("Number of observed packets") .Register(*registry); - // add a counter to the metric family - auto& second_counter = counter_family.Add( - {{"another_label", "value"}, {"yet_another_label", "value"}}); + // add and remember dimensional data, incrementing those is very cheap + auto& tcp_rx_counter = + packet_counter.Add({{"protocol", "tcp"}, {"direction", "rx"}}); + auto& tcp_tx_counter = + packet_counter.Add({{"protocol", "tcp"}, {"direction", "tx"}}); + auto& udp_rx_counter = + packet_counter.Add({{"protocol", "udp"}, {"direction", "rx"}}); + auto& udp_tx_counter = + packet_counter.Add({{"protocol", "udp"}, {"direction", "tx"}}); - // ask the exposer to scrape the registry on incoming scrapes + // add a counter whose dimensional data is not known at compile time + // nevertheless dimensional values should only occur in low cardinality: + // https://prometheus.io/docs/practices/naming/#labels + auto& http_requests_counter = BuildCounter() + .Name("http_requests_total") + .Help("Number of HTTP requests") + .Register(*registry); + + // ask the exposer to scrape the registry on incoming HTTP requests exposer.RegisterCollectable(registry); for (;;) { std::this_thread::sleep_for(std::chrono::seconds(1)); - // increment the counter by one (second) - second_counter.Increment(); + const auto random_value = std::rand(); + + if (random_value & 1) tcp_rx_counter.Increment(); + if (random_value & 2) tcp_tx_counter.Increment(); + if (random_value & 4) udp_rx_counter.Increment(); + if (random_value & 8) udp_tx_counter.Increment(); + + const std::array methods = {"GET", "PUT", "POST", "HEAD"}; + auto method = methods.at(random_value % methods.size()); + // dynamically calling Family.Add() works but is slow and should be + // avoided + http_requests_counter.Add({{"method", method}}).Increment(); } return 0; } diff --git a/pull/tests/integration/scrape.sh b/pull/tests/integration/scrape.sh index a91f233e..5b1297f1 100755 --- a/pull/tests/integration/scrape.sh +++ b/pull/tests/integration/scrape.sh @@ -16,4 +16,4 @@ trap 'kill $(jobs -p)' EXIT timeout_after 10 pull/tests/integration/sample-server & -telegraf --config pull/tests/integration/scrape.conf --quiet | grep -m1 time_running_seconds_total +telegraf --config pull/tests/integration/scrape.conf --quiet | grep -m1 http_requests_total From 8e02f8ff8b845d768a89f7fb5eee92268ed5f82f Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 26 Dec 2020 22:13:27 +0100 Subject: [PATCH 135/206] ci: Make Coverage workflow more fine-grained --- .github/scripts/run-cmake-coverage | 20 ---------- .github/scripts/run-prepare | 29 -------------- .github/workflows/cmake-ci.yml | 10 ++--- .github/workflows/coverage.yml | 64 +++++++++++++++++++++++------- 4 files changed, 54 insertions(+), 69 deletions(-) delete mode 100755 .github/scripts/run-cmake-coverage delete mode 100755 .github/scripts/run-prepare diff --git a/.github/scripts/run-cmake-coverage b/.github/scripts/run-cmake-coverage deleted file mode 100755 index 1dc61ef4..00000000 --- a/.github/scripts/run-cmake-coverage +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -WORKSPACE=$(cd "$(dirname "${BASH_SOURCE[0]}")"/../.. && /bin/pwd -P) -PATH=$HOME/.local/bin:$PATH - -pip install --user cpp-coveralls - -# Build with coverage - -mkdir "${WORKSPACE}/_build_coverage" && cd $_ -CFLAGS="--coverage" CXXFLAGS="--coverage" LDFLAGS="--coverage" cmake .. -DUSE_THIRDPARTY_LIBRARIES=OFF "-DCMAKE_TOOLCHAIN_FILE=${VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake" -make -j$(nproc) -ctest -V -LE Benchmark - -# Collect coverage data - -export TRAVIS_BRANCH=${GITHUB_REF} -coveralls --root .. --build-root . --gcov-options '\-lp' -E ".*/3rdparty/.*" -E ".*/_.*" -E ".*/tests/.*" -E ".*/benchmarks/.*" -E "./CMake.*CompilerId.c" diff --git a/.github/scripts/run-prepare b/.github/scripts/run-prepare deleted file mode 100755 index e80d1276..00000000 --- a/.github/scripts/run-prepare +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -BUILDSYSTEM_ARG=${1:?} -OS_ARG=${2:?} - -case "${OS_ARG}" in - ubuntu*) - packages=(locales) - - case "${BUILDSYSTEM_ARG}" in - cmake) - packages+=(python-pip python-wheel) - ;; - esac - - sudo apt-get remove -y --purge man-db # avoid time-consuming trigger - sudo apt-get update - sudo apt-get install -y "${packages[@]}" - sudo locale-gen de_DE.UTF-8 # used by SerializerTest - ;; -esac - -case "${BUILDSYSTEM_ARG}" in - cmake) - "${VCPKG_INSTALLATION_ROOT}/vcpkg" install benchmark civetweb curl gtest zlib - ;; -esac diff --git a/.github/workflows/cmake-ci.yml b/.github/workflows/cmake-ci.yml index 4e5fca9c..2b8c0b8f 100644 --- a/.github/workflows/cmake-ci.yml +++ b/.github/workflows/cmake-ci.yml @@ -11,7 +11,7 @@ jobs: os: [macOS-latest, ubuntu-18.04, windows-2016] dependencies: [submodule, vcpkg] steps: - - name: Checkout source + - name: Checkout source uses: actions/checkout@v2 - name: Checkout submodules @@ -27,9 +27,9 @@ jobs: uses: actions/cache@v2 with: path: "~/.cache/vcpkg/archives" - key: vcpkg-${{ runner.os }} + key: vcpkg-${{ matrix.os }} - - name: install vcpkg dependencies + - name: Install vcpkg dependencies if: matrix.dependencies == 'vcpkg' run: vcpkg install benchmark civetweb curl[core] gtest zlib @@ -41,12 +41,12 @@ jobs: sudo apt-get install -y locales sudo locale-gen de_DE.UTF-8 # used by SerializerTest - - name: install ninja on Ubuntu + - name: Install ninja on Ubuntu if: runner.os == 'Linux' run: | sudo apt-get install -y ninja-build - - name: install ninja on macOS + - name: Install ninja on macOS if: runner.os == 'macOS' run: brew install ninja diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 53c8f88b..0c40e95f 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -3,25 +3,59 @@ on: [push, pull_request] jobs: build: - name: Coverage ${{ matrix.buildsystem }} on ${{ matrix.os }} - runs-on: ${{ matrix.os }} - strategy: - matrix: - buildsystem: [cmake] - os: [ubuntu-16.04] + name: Code Coverage + runs-on: ubuntu-16.04 steps: - - uses: actions/checkout@master - - name: Checkout submodules - shell: bash + - name: Checkout source + uses: actions/checkout@v2 + + - name: Mount vcpkg cache + uses: actions/cache@v2 + with: + path: "~/.cache/vcpkg/archives" + key: vcpkg-${{ matrix.os }} + + - name: Install vcpkg dependencies + run: vcpkg install benchmark civetweb curl[core] gtest zlib + + - name: Generate German locale on Ubuntu + if: runner.os == 'Linux' + run: | + sudo apt-get remove -y --purge man-db # avoid time-consuming trigger + sudo apt-get update + sudo apt-get install -y locales + sudo locale-gen de_DE.UTF-8 # used by SerializerTest + + - name: Install ninja on Ubuntu + if: runner.os == 'Linux' + run: | + sudo apt-get install -y ninja-build + + - name: Install coveralls + if: runner.os == 'Linux' run: | - auth_header="$(git config --local --get http.https://github.com/.extraheader)" - git submodule sync --recursive - git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1 - - name: Prepare - run: .github/scripts/run-prepare ${{ matrix.buildsystem }} ${{ matrix.os }} + sudo apt-get install -y python-pip python-wheel + pip install --user cpp-coveralls + + - name: "CMake Configure for Unix with vcpkg dependencies" + env: + CFLAGS: "--coverage" + CXXFLAGS: "--coverage" + LDFLAGS: "--coverage" + run: cmake -DUSE_THIRDPARTY_LIBRARIES=OFF "-DCMAKE_TOOLCHAIN_FILE=${VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake" -GNinja -S ${{ github.workspace }} -B ${{ github.workspace }}/_build + + - name: Build + run: cmake --build ${{ github.workspace }}/_build + - name: Test + run: ctest -V -LE Benchmark + working-directory: "${{ github.workspace }}/_build" + + - name: Upload Coverage if: github.repository == 'jupp0r/prometheus-cpp' env: COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} COVERALLS_GIT_BRANCH: "${{ github.ref }}" - run: .github/scripts/run-cmake-coverage + TRAVIS_BRANCH: "${{ github.ref }}" + working-directory: "${{ github.workspace }}/_build" + run: ~/.local/bin/coveralls --root .. --build-root . --gcov-options '\-lp' -E ".*/3rdparty/.*" -E ".*/_.*" -E ".*/tests/.*" -E ".*/benchmarks/.*" -E "./CMake.*CompilerId.c" -E ".*/cmake/.*" From eae808770abeedc30e17ded97aac463c6d32c67c Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 26 Dec 2020 23:28:15 +0100 Subject: [PATCH 136/206] pull: test authentication and compression --- pull/tests/integration/integration_test.cc | 62 ++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/pull/tests/integration/integration_test.cc b/pull/tests/integration/integration_test.cc index c7fe6b55..f8ccaa5a 100644 --- a/pull/tests/integration/integration_test.cc +++ b/pull/tests/integration/integration_test.cc @@ -1,6 +1,7 @@ #include #include +#include #include #include @@ -27,6 +28,8 @@ class IntegrationTest : public testing::Test { std::string body; }; + std::function fetchPrePerform_; + Resonse FetchMetrics(std::string metrics_path) { auto curl = std::shared_ptr(curl_easy_init(), curl_easy_cleanup); if (!curl) { @@ -40,6 +43,10 @@ class IntegrationTest : public testing::Test { curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &response.body); curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, WriteCallback); + if (fetchPrePerform_) { + fetchPrePerform_(curl.get()); + } + CURLcode curl_error = curl_easy_perform(curl.get()); if (curl_error != CURLE_OK) { throw std::runtime_error("failed to perform HTTP request"); @@ -134,5 +141,60 @@ TEST_F(IntegrationTest, unexposeRegistry) { EXPECT_THAT(metrics.body, Not(HasSubstr(counter_name))); } +TEST_F(IntegrationTest, acceptOptionalCompression) { + const std::string counter_name = "example_total"; + auto registry = RegisterSomeCounter(counter_name, default_metrics_path_); + + fetchPrePerform_ = [](CURL* curl) { + curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, ""); + }; + const auto metrics = FetchMetrics(default_metrics_path_); + + ASSERT_EQ(metrics.code, 200); + EXPECT_THAT(metrics.body, HasSubstr(counter_name)); +} + +TEST_F(IntegrationTest, shouldRejectRequestWithoutAuthorization) { + const std::string counter_name = "example_total"; + auto registry = RegisterSomeCounter(counter_name, default_metrics_path_); + + exposer_->RegisterAuth( + [](const std::string& user, const std::string& password) { + return user == "test_user" && password == "test_password"; + }, + "Some Auth Realm", default_metrics_path_); + + const auto metrics = FetchMetrics(default_metrics_path_); + + ASSERT_EQ(metrics.code, 401); + EXPECT_THAT(metrics.body, HasSubstr(counter_name)); +} + +TEST_F(IntegrationTest, shouldPerformProperAuthentication) { + const std::string counter_name = "example_total"; + auto registry = RegisterSomeCounter(counter_name, default_metrics_path_); + + const auto my_username = "test_user"; + const auto my_password = "test_password"; + + fetchPrePerform_ = [my_username, my_password](CURL* curl) { + curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + curl_easy_setopt(curl, CURLOPT_USERNAME, my_username); + curl_easy_setopt(curl, CURLOPT_PASSWORD, my_password); + }; + + exposer_->RegisterAuth( + [my_username, my_password](const std::string& user, const std::string& password) { + return user == my_username && password == my_password; + }, + "Some Auth Realm", default_metrics_path_); + + const auto metrics = FetchMetrics(default_metrics_path_); + + ASSERT_EQ(metrics.code, 200); + EXPECT_THAT(metrics.body, HasSubstr(counter_name)); +} + + } // namespace } // namespace prometheus From 114f756f19de5e823dfa7a6e3ab18691d81f04c0 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 27 Dec 2020 00:48:26 +0100 Subject: [PATCH 137/206] pull: don't set auth handler to nullptr to avoid civetweb bug --- pull/src/endpoint.cc | 11 ++++++++++- pull/tests/integration/integration_test.cc | 1 - 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/pull/src/endpoint.cc b/pull/src/endpoint.cc index 0e9f746f..68d42a4d 100644 --- a/pull/src/endpoint.cc +++ b/pull/src/endpoint.cc @@ -7,6 +7,14 @@ namespace prometheus { namespace detail { +namespace { +class AlwaysAllowAccessHandler : public CivetAuthHandler { + bool authorize(CivetServer*, struct mg_connection*) override { return true; } +}; + +AlwaysAllowAccessHandler alwaysAllowAccessHandler; +} // namespace + Endpoint::Endpoint(CivetServer& server, std::string uri) : server_(server), uri_(std::move(uri)), @@ -21,7 +29,8 @@ Endpoint::~Endpoint() { server_.removeHandler(uri_); if (auth_handler_) { // work-around https://github.com/civetweb/civetweb/issues/941 - server_.removeAuthHandler(uri_); + // server_.removeAuthHandler(uri_); + server_.addAuthHandler(uri_, alwaysAllowAccessHandler); } } diff --git a/pull/tests/integration/integration_test.cc b/pull/tests/integration/integration_test.cc index f8ccaa5a..7c0c201c 100644 --- a/pull/tests/integration/integration_test.cc +++ b/pull/tests/integration/integration_test.cc @@ -167,7 +167,6 @@ TEST_F(IntegrationTest, shouldRejectRequestWithoutAuthorization) { const auto metrics = FetchMetrics(default_metrics_path_); ASSERT_EQ(metrics.code, 401); - EXPECT_THAT(metrics.body, HasSubstr(counter_name)); } TEST_F(IntegrationTest, shouldPerformProperAuthentication) { From b8db5e468d0685ee1f28c242a607f6777390e5cc Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 27 Dec 2020 00:49:56 +0100 Subject: [PATCH 138/206] pull: don't trigger failing authentication due to civetweb/civetweb#954 --- pull/tests/integration/integration_test.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pull/tests/integration/integration_test.cc b/pull/tests/integration/integration_test.cc index 7c0c201c..43dfbe8c 100644 --- a/pull/tests/integration/integration_test.cc +++ b/pull/tests/integration/integration_test.cc @@ -154,6 +154,7 @@ TEST_F(IntegrationTest, acceptOptionalCompression) { EXPECT_THAT(metrics.body, HasSubstr(counter_name)); } +#if 0 // https://github.com/civetweb/civetweb/issues/954 TEST_F(IntegrationTest, shouldRejectRequestWithoutAuthorization) { const std::string counter_name = "example_total"; auto registry = RegisterSomeCounter(counter_name, default_metrics_path_); @@ -168,6 +169,7 @@ TEST_F(IntegrationTest, shouldRejectRequestWithoutAuthorization) { ASSERT_EQ(metrics.code, 401); } +#endif TEST_F(IntegrationTest, shouldPerformProperAuthentication) { const std::string counter_name = "example_total"; From 58dbe7815391b20894d457d8a9048a37a156997f Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 27 Dec 2020 13:25:44 +0100 Subject: [PATCH 139/206] ci: use lcov for coverage --- .github/workflows/coverage.yml | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 0c40e95f..6cfb1c7d 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -4,7 +4,7 @@ on: [push, pull_request] jobs: build: name: Code Coverage - runs-on: ubuntu-16.04 + runs-on: ubuntu-20.04 steps: - name: Checkout source uses: actions/checkout@v2 @@ -13,7 +13,7 @@ jobs: uses: actions/cache@v2 with: path: "~/.cache/vcpkg/archives" - key: vcpkg-${{ matrix.os }} + key: vcpkg-${{ runner.os }} - name: Install vcpkg dependencies run: vcpkg install benchmark civetweb curl[core] gtest zlib @@ -31,11 +31,10 @@ jobs: run: | sudo apt-get install -y ninja-build - - name: Install coveralls + - name: Install lcov if: runner.os == 'Linux' run: | - sudo apt-get install -y python-pip python-wheel - pip install --user cpp-coveralls + sudo apt-get install -y lcov - name: "CMake Configure for Unix with vcpkg dependencies" env: @@ -51,11 +50,11 @@ jobs: run: ctest -V -LE Benchmark working-directory: "${{ github.workspace }}/_build" - - name: Upload Coverage - if: github.repository == 'jupp0r/prometheus-cpp' - env: - COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} - COVERALLS_GIT_BRANCH: "${{ github.ref }}" - TRAVIS_BRANCH: "${{ github.ref }}" - working-directory: "${{ github.workspace }}/_build" - run: ~/.local/bin/coveralls --root .. --build-root . --gcov-options '\-lp' -E ".*/3rdparty/.*" -E ".*/_.*" -E ".*/tests/.*" -E ".*/benchmarks/.*" -E "./CMake.*CompilerId.c" -E ".*/cmake/.*" + - name: Run lcov + run: lcov --capture --directory "${{ github.workspace }}/_build" --output-file coverage.info --no-external --directory "${{ github.workspace }}" --exclude '*/tests/*' + + - name: Coveralls + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + path-to-lcov: coverage.info From b57ad1d998c193f60fe5cf18df9af705ee190728 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 27 Dec 2020 15:43:17 +0100 Subject: [PATCH 140/206] ci: Use GitHub Actions to deploy documentation --- .github/workflows/doxygen.yml | 30 ++++++++++++++++++++++++++++++ .travis.yml | 30 ------------------------------ 2 files changed, 30 insertions(+), 30 deletions(-) create mode 100644 .github/workflows/doxygen.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml new file mode 100644 index 00000000..5edbd7a9 --- /dev/null +++ b/.github/workflows/doxygen.yml @@ -0,0 +1,30 @@ +name: Doxygen +on: + push: + branches: + - master + +jobs: + build: + name: Code Coverage + runs-on: ubuntu-20.04 + steps: + - name: Checkout source + uses: actions/checkout@v2 + + - name: Install doxygen + run: | + sudo apt-get remove -y --purge man-db # avoid time-consuming trigger + sudo apt-get update + sudo apt-get install -y doxygen graphviz + + - name: Generate doxygen + run: doxygen + working-directory: "${{ github.workspace }}/doc" + + - name: Deploy documentation + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + force_orphan: true + publish_dir: ./doc/html diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index bc2d87c5..00000000 --- a/.travis.yml +++ /dev/null @@ -1,30 +0,0 @@ -sudo: required -dist: bionic -language: c++ - -env: - global: - - secure: "DwlWRs05m1pw3/NprZdVRy3Vog7k+KYIW4O1YQczbKk0t64vYLJMxMh9D8HrngnUv1UDOOU2orEO/hYYjlmiNRqoMA0Me+q9ndqEGjdCvFketH7zYpPXMxV/Uk1E7yYK60CJYbCFK7NossBWlBwSIETUNXXz1MhqF4c7SwDCTQk6ybPUThJVI3/nZLC4Wn9DB4pxPkEZaXJLL3HU0vXH1r0vKRFsjBU0OtDx1KQgtFYVmWbmd7tpxAlDfI11HJjpaoFD6HHcTlwvM5Ogj4lWL8Ze3glJsSsAYntEqgm7GQa4tYWsYmvGC5554WwIQ/0cDsSTLZjk2+FtSGmJpxdwXwmfOzzVjt7Ise7KG2Zg+CZ/IwF9VpwP2xmH/ug926sJDIjMmehZx2eetDzwY3oB3g3AF+JJIoaDF14Skt6QXEFWm/s/PiSQwkenMF80xzUufB7CRCVLR054HfJsQ0m5O8bNtUjyH7byZwOjvz8t/VdlnfFn5Ccs4tniOK6iiwvKmGAaakv6pfA7xKpRbExFkgPoTmejeQX83Ee1/A4JySMPTxkHPsJbMhimpMdbLVJTh9mKJxo2kleCC0MKB7OwTyNwUdR8+nqoZpUknGX6BrGY+R6ou3xlNYRUM9LCxxBKBJB05CswbhRWroun9fbpDTzBz3XPwBjiVTlxUc/YnXA=" - - secure: "fg0cACBBm7NAjad4Pxhp9DeTGDbcLnD0U9uxclsioTcB5X+88sTsgKRr5gG0hajPG6QF0L8iNt7zp87eZNcSU7JlTWnCBHPAAADD2apFnPUhioth+vPUBsUiKdOksoEG1q/hrjMYQ6yAf3XXd0+/ZaUA1X5v0OA2rjMTpNpNvMaQEN7M3XvcLRr1ydaAD/Wc1PAbuK8owWU3Hyo7+GdxoUWOtYiH44OuHSlSlnVQw2/yRR53yM1StKLZ2xarsWviXr76e1PutqoeeTbBbpAU6xboiyyDVey4Ae83HfOgPiADtsE4UjE2pqX2oqponY2q+0j8kI7sZVODR20nLCKcq9RHJR+yi0JEpsrqC4SE0lPKxG8HHlDaH+NdRVHTdNYuCfENR0R4YX/K59I83kLEnLNpC+j1BzXiRBjYzAMl5UtEDCUQGJcixq6BxE7i1uwskPckmYi2K63TaIxj5nvVm4Um8aHPrWHtbAf4stTDQHcFGcfQeBbX7PswKJAyIljaHn5T7kwAatRuWLHGsVTuxTkhkYohZy+/SDhFakI+6jfz8XZtL8gOIGMnDuvDWT2Di1JPZkBLcKKWpCIXdDaJnTogNid9xBpsX5IMVmlS51FxCOkoIT62gc9Lo+rxwgqFvEe+QIQh2zd8OjgS5m5HsftxCKVCbcPr+RjsNsCyOnQ=" - - secure: "ijrdtLO7y18oJTcISP1Zl0+O8dbCmo8DB4+3N6kZ9JjL1rVF5NM9nCsaCQ6vmHFOsUjEehvGJR6ZYFOYOMBU11rCPqd2FrEPewtQ0qEYI8eOV062oa/DOxHKyzGPde8eHcopw6b44EjPXx4iZTabcU8U00azNyWinVxKtP8lHJiVH+waNejuoAuMKypM9Lz+RCz/TLg4+DpLvQ5kWfpcFsuBCBAMbCK6Ujmv5mscvKxmWLr2Z79Wl3i5MbBe3IuaDAKXTz0ponkvZCssPr/USD9AA04EEn/Eg95JXOtRUi6Ah/fUBDAF4Ez/7yOHsXD1y8xt332eE8nJqjX3eLqEdplT19M/hBsbXxNCL0iZSZ8LL0JHKYG5beDGvfZmrk4/Nj/qd3Es1NGT6q2kbkrbxWSEFdkniQuwfr+yvAoGv4XFdRMTPH321WrL8wxfud0b2OPMMJo6obDOgRZfHe6c+4Eo9i/G98eL7xOz0kUUILiex8IQKNWnYflH1CqRKBbNs0APAMMlFKQ8FVwLiu/OzA8mjI+CuPGxOdfilgsJfCvKMBvz12y2AIBHdVBf1T6Ph8NZpwKivNYt70QOu5J/rg5K6E6XY1faMgWuDzQkMaeof1esU1IVlXqKBWa9c9rMNHQHTvhZ2KZ1EZvNrCX1fnY/X8fuwnhJ1Aq1nzhJTrM=" - -addons: - apt: - packages: - - doxygen - - graphviz - -script: - - pushd . - - cd doc - - doxygen - - touch html/.nojekyll - - popd - -deploy: - provider: pages - local-dir: doc/html - github-token: $GITHUB_TOKEN - skip-cleanup: true - on: - branch: master From 3c5d3c5775d70d0fbe6a3f2b0ecdbb77f80e3acb Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 27 Dec 2020 17:50:36 +0100 Subject: [PATCH 141/206] pull: improve code coverage --- pull/tests/integration/integration_test.cc | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/pull/tests/integration/integration_test.cc b/pull/tests/integration/integration_test.cc index 43dfbe8c..e5832c1d 100644 --- a/pull/tests/integration/integration_test.cc +++ b/pull/tests/integration/integration_test.cc @@ -196,6 +196,28 @@ TEST_F(IntegrationTest, shouldPerformProperAuthentication) { EXPECT_THAT(metrics.body, HasSubstr(counter_name)); } +TEST_F(IntegrationTest, shouldDealWithExpiredCollectables) { + const std::string first_counter_name = "first_total"; + const std::string second_counter_name = "second_total"; + + const auto registry = + RegisterSomeCounter(first_counter_name, default_metrics_path_); + auto disappearing_registry = + RegisterSomeCounter(second_counter_name, default_metrics_path_); + + disappearing_registry.reset(); + + // all set-up + + const auto metrics = FetchMetrics(default_metrics_path_); + + // check results + + ASSERT_EQ(metrics.code, 200); + + EXPECT_THAT(metrics.body, HasSubstr(first_counter_name)); + EXPECT_THAT(metrics.body, Not(HasSubstr(second_counter_name))); +} } // namespace } // namespace prometheus From e0cc7b5e3ecde5afc9f3f0f00f38ef7bdd321491 Mon Sep 17 00:00:00 2001 From: Hubert Bugaj Date: Mon, 4 Jan 2021 13:04:48 +0100 Subject: [PATCH 142/206] Added missing include --- core/src/histogram.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/histogram.cc b/core/src/histogram.cc index 80235298..b298fd4b 100644 --- a/core/src/histogram.cc +++ b/core/src/histogram.cc @@ -3,6 +3,7 @@ #include #include #include +#include #include #include From da316fca3d81e444a8778856a97e22cab2986ac6 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Tue, 5 Jan 2021 06:06:14 +0100 Subject: [PATCH 143/206] ci: Add workflow to create tarball including submodules Closes: #388 --- .github/workflows/release.yml | 38 +++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..342d3f68 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,38 @@ +on: + release: + types: [created] + +name: Handle Release + +jobs: + build: + name: Upload Release Asset + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Checkout submodules + shell: bash + run: | + auth_header="$(git config --local --get http.https://github.com/.extraheader)" + git submodule sync --recursive + git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1 + + - name: Create tarball including submodules + shell: bash + env: + PREFIX: prometheus-cpp-with-submodules + run: | + git archive --prefix "${PREFIX}/" -o "${PREFIX}.tar" HEAD + git submodule foreach --recursive "git archive --prefix=${PREFIX}/\$path/ --output=\$sha1.tar HEAD && tar --concatenate --file=$(pwd)/${PREFIX}.tar \$sha1.tar && rm \$sha1.tar" + gzip "${PREFIX}.tar" + + # using the official actions/upload-release-asset action would be preferred but is blocked by + # https://github.com/actions/upload-release-asset/pull/41 + - name: Upload the artifacts + uses: skx/github-action-publish-binaries@75ce5546020fc1848da842f40240f9fa03e7a3a8 # release-0.14 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + args: prometheus-cpp-with-submodules.tar.gz From bf0ddfc57b1badcdf48b826d0e24044c9824aaa7 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 10 Jan 2021 00:31:14 +0100 Subject: [PATCH 144/206] fix: use printf %g or std::to_chars to serialize doubles This will result in floating point numbers redered with the necessary precision and avoids trailing zeroes. Closes: #441 --- core/src/text_serializer.cc | 36 ++++++++++++++++++++++-------- core/tests/serializer_test.cc | 2 +- core/tests/text_serializer_test.cc | 24 +++++++++----------- 3 files changed, 38 insertions(+), 24 deletions(-) diff --git a/core/src/text_serializer.cc b/core/src/text_serializer.cc index c0267941..d73964b2 100644 --- a/core/src/text_serializer.cc +++ b/core/src/text_serializer.cc @@ -1,10 +1,17 @@ #include "prometheus/text_serializer.h" +#include #include -#include -#include #include #include +#include + +#if __cpp_lib_to_chars >= 201611L +#include +#else +#include +#include +#endif namespace prometheus { @@ -17,14 +24,25 @@ void WriteValue(std::ostream& out, double value) { } else if (std::isinf(value)) { out << (value < 0 ? "-Inf" : "+Inf"); } else { - std::ios oldState{nullptr}; - oldState.copyfmt(out); + std::array buffer; - out.setf(std::ios::fixed, std::ios::floatfield); - out << std::setprecision(std::numeric_limits::max_digits10); - out << value; - - out.copyfmt(oldState); +#if __cpp_lib_to_chars >= 201611L + auto [ptr, ec] = + std::to_chars(buffer.data(), buffer.data() + buffer.size(), value); + if (ec != std::errc()) { + throw std::runtime_error("Could not convert double to string: " + ec); + } + out.write(buffer.data(), ptr - buffer.data()); +#else + auto wouldHaveWritten = + std::snprintf(buffer.data(), buffer.size(), "%.*g", + std::numeric_limits::max_digits10 - 1, value); + if (wouldHaveWritten <= 0 || + static_cast(wouldHaveWritten) >= buffer.size()) { + throw std::runtime_error("Could not convert double to string"); + } + out.write(buffer.data(), wouldHaveWritten); +#endif } } diff --git a/core/tests/serializer_test.cc b/core/tests/serializer_test.cc index 7e9e26a3..528f649d 100644 --- a/core/tests/serializer_test.cc +++ b/core/tests/serializer_test.cc @@ -43,7 +43,7 @@ TEST_F(SerializerTest, shouldSerializeLocaleIndependent) { } const auto serialized = textSerializer.Serialize(collected); - EXPECT_THAT(serialized, testing::HasSubstr("1.0")); + EXPECT_THAT(serialized, testing::HasSubstr(" 1\n")); } #endif diff --git a/core/tests/text_serializer_test.cc b/core/tests/text_serializer_test.cc index bacd5345..6b9bc479 100644 --- a/core/tests/text_serializer_test.cc +++ b/core/tests/text_serializer_test.cc @@ -69,7 +69,7 @@ TEST_F(TextSerializerTest, shouldSerializeUntyped) { metric.untyped.value = 64.0; const auto serialized = Serialize(MetricType::Untyped); - EXPECT_THAT(serialized, testing::HasSubstr(name + " 64.00000000000000000")); + EXPECT_THAT(serialized, testing::HasSubstr(name + " 64\n")); } TEST_F(TextSerializerTest, shouldSerializeTimestamp) { @@ -77,8 +77,7 @@ TEST_F(TextSerializerTest, shouldSerializeTimestamp) { metric.timestamp_ms = 1234; const auto serialized = Serialize(MetricType::Counter); - EXPECT_THAT(serialized, - testing::HasSubstr(name + " 64.00000000000000000 1234")); + EXPECT_THAT(serialized, testing::HasSubstr(name + " 64 1234\n")); } TEST_F(TextSerializerTest, shouldSerializeHistogramWithNoBuckets) { @@ -87,7 +86,7 @@ TEST_F(TextSerializerTest, shouldSerializeHistogramWithNoBuckets) { const auto serialized = Serialize(MetricType::Histogram); EXPECT_THAT(serialized, testing::HasSubstr(name + "_count 2")); - EXPECT_THAT(serialized, testing::HasSubstr(name + "_sum 32.000000000000000")); + EXPECT_THAT(serialized, testing::HasSubstr(name + "_sum 32\n")); EXPECT_THAT(serialized, testing::HasSubstr(name + "_bucket{le=\"+Inf\"} 2")); } @@ -98,11 +97,11 @@ TEST_F(TextSerializerTest, shouldSerializeHistogram) { metric = histogram.Collect(); const auto serialized = Serialize(MetricType::Histogram); - EXPECT_THAT(serialized, testing::HasSubstr(name + "_count 2")); - EXPECT_THAT(serialized, testing::HasSubstr(name + "_sum 200.00000000000000")); - EXPECT_THAT(serialized, testing::HasSubstr( - name + "_bucket{le=\"1.00000000000000000\"} 1")); - EXPECT_THAT(serialized, testing::HasSubstr(name + "_bucket{le=\"+Inf\"} 2")); + EXPECT_THAT(serialized, testing::HasSubstr(name + "_count 2\n")); + EXPECT_THAT(serialized, testing::HasSubstr(name + "_sum 200\n")); + EXPECT_THAT(serialized, testing::HasSubstr(name + "_bucket{le=\"1\"} 1\n")); + EXPECT_THAT(serialized, + testing::HasSubstr(name + "_bucket{le=\"+Inf\"} 2\n")); } TEST_F(TextSerializerTest, shouldSerializeSummary) { @@ -113,11 +112,8 @@ TEST_F(TextSerializerTest, shouldSerializeSummary) { const auto serialized = Serialize(MetricType::Summary); EXPECT_THAT(serialized, testing::HasSubstr(name + "_count 2")); - EXPECT_THAT(serialized, testing::HasSubstr(name + "_sum 200.00000000000000")); - EXPECT_THAT( - serialized, - testing::HasSubstr( - name + "{quantile=\"0.50000000000000000\"} 0.0000000000000000")); + EXPECT_THAT(serialized, testing::HasSubstr(name + "_sum 200\n")); + EXPECT_THAT(serialized, testing::HasSubstr(name + "{quantile=\"0.5\"} 0\n")); } } // namespace From 6929e34e86e8c2dbcf5eacf848b212f27a7fac77 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Fri, 5 Feb 2021 12:56:24 +0100 Subject: [PATCH 145/206] chore: start prometheus-cpp 0.12.1 development cycle --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ebb94353..9ac303a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ if(POLICY CMP0091) cmake_policy(SET CMP0091 NEW) # recognize CMAKE_MSVC_RUNTIME_LIBRARY endif() -project(prometheus-cpp VERSION 0.12.0) +project(prometheus-cpp VERSION 0.12.1) include(GenerateExportHeader) include(GNUInstallDirs) From 58141879f69f709f4bba56aa4253c0a069278d9b Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Fri, 5 Feb 2021 12:56:29 +0100 Subject: [PATCH 146/206] core: Fix usage of std::to_chars --- core/src/text_serializer.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/src/text_serializer.cc b/core/src/text_serializer.cc index d73964b2..858c6150 100644 --- a/core/src/text_serializer.cc +++ b/core/src/text_serializer.cc @@ -8,6 +8,8 @@ #if __cpp_lib_to_chars >= 201611L #include +#include +#include #else #include #include @@ -30,7 +32,8 @@ void WriteValue(std::ostream& out, double value) { auto [ptr, ec] = std::to_chars(buffer.data(), buffer.data() + buffer.size(), value); if (ec != std::errc()) { - throw std::runtime_error("Could not convert double to string: " + ec); + throw std::runtime_error("Could not convert double to string: " + + std::make_error_code(ec).message()); } out.write(buffer.data(), ptr - buffer.data()); #else From a0994305f57956448cea3ac4e822caf993190d89 Mon Sep 17 00:00:00 2001 From: Ivan Fefer Date: Wed, 10 Feb 2021 11:16:55 +0300 Subject: [PATCH 147/206] Add conan reference to readme --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index cd289c95..68e48918 100644 --- a/README.md +++ b/README.md @@ -214,6 +214,11 @@ example project and minimal [CMakeLists.txt](cmake/project-import/CMakeLists.txt The [vcpkg](https://github.com/microsoft/vcpkg) package manager contains a prometheus-cpp port which has been tested on Linux, macOS, and Windows. +### Conan + +[Conan](https://conan.io/) package manager contains prometheus-cpp package as well +in [ConanCenter](https://conan.io/center/prometheus-cpp) repository + ### Plain Makefiles When manually linking prometheus-cpp the library order matters. The needed From f448b2c3de42a89521a2d44850e8a82aa0878d84 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Wed, 3 Mar 2021 21:35:26 +0100 Subject: [PATCH 148/206] feat(iwyu): Organize includes with include-what-you-use --- .github/workflows/linting.yml | 40 +++++++++++ CMakeLists.txt | 20 ++++++ cmake/civetweb-3rdparty-config.cmake | 5 ++ cmake/googlemock-3rdparty-config.cmake | 7 +- cmake/googletest.imp | 4 ++ cmake/project-import/sample_client.cc | 66 +------------------ core/benchmarks/benchmark_helpers.cc | 4 +- core/benchmarks/benchmark_helpers.h | 3 +- core/benchmarks/counter_bench.cc | 8 ++- core/benchmarks/gauge_bench.cc | 8 ++- core/benchmarks/histogram_bench.cc | 8 ++- core/benchmarks/registry_bench.cc | 5 +- core/benchmarks/summary_bench.cc | 10 ++- core/include/prometheus/counter.h | 2 +- core/include/prometheus/detail/builder.h | 7 +- .../prometheus/detail/ckms_quantiles.h | 2 + .../prometheus/detail/time_window_quantiles.h | 4 +- core/include/prometheus/family.h | 11 ++-- core/include/prometheus/gauge.h | 2 +- core/include/prometheus/histogram.h | 2 +- core/include/prometheus/registry.h | 3 +- core/include/prometheus/summary.h | 2 +- core/include/prometheus/text_serializer.h | 1 - core/src/check_names.cc | 2 + core/src/detail/builder.cc | 1 + core/src/detail/ckms_quantiles.cc | 3 +- core/src/detail/time_window_quantiles.cc | 5 +- core/src/detail/utils.cc | 2 +- core/src/family.cc | 6 ++ core/src/histogram.cc | 4 +- core/src/registry.cc | 4 ++ core/src/serializer.cc | 2 +- core/src/summary.cc | 2 + core/src/text_serializer.cc | 5 ++ core/tests/builder_test.cc | 11 +++- core/tests/check_names_test.cc | 2 +- core/tests/counter_test.cc | 2 +- core/tests/family_test.cc | 2 + core/tests/gauge_test.cc | 2 +- core/tests/histogram_test.cc | 4 +- core/tests/registry_test.cc | 4 +- core/tests/serializer_test.cc | 5 ++ core/tests/summary_test.cc | 4 +- core/tests/text_serializer_test.cc | 7 +- core/tests/utils_test.cc | 3 +- pull/include/prometheus/exposer.h | 4 +- pull/src/basic_auth.cc | 3 +- pull/src/basic_auth.h | 3 +- pull/src/detail/base64.h | 1 + pull/src/endpoint.cc | 2 + pull/src/endpoint.h | 4 +- pull/src/exposer.cc | 7 +- pull/src/handler.cc | 12 +++- pull/src/handler.h | 2 + pull/src/metrics_collector.cc | 2 + pull/tests/integration/integration_test.cc | 10 ++- pull/tests/integration/sample_server.cc | 10 +-- pull/tests/integration/sample_server_auth.cc | 11 ++-- pull/tests/integration/sample_server_multi.cc | 11 ++-- pull/tests/unit/exposer_test.cc | 2 +- push/include/prometheus/gateway.h | 5 +- push/src/gateway.cc | 8 ++- push/tests/integration/sample_client.cc | 12 ++-- 63 files changed, 264 insertions(+), 151 deletions(-) create mode 100644 .github/workflows/linting.yml create mode 100644 cmake/googletest.imp mode change 100644 => 120000 cmake/project-import/sample_client.cc diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml new file mode 100644 index 00000000..557edeaa --- /dev/null +++ b/.github/workflows/linting.yml @@ -0,0 +1,40 @@ +name: Linting +on: [push, pull_request] + +jobs: + build: + name: Include What You Use + runs-on: ubuntu-20.04 + steps: + - name: Checkout source + uses: actions/checkout@v2 + + - name: Checkout submodules + shell: bash + run: | + auth_header="$(git config --local --get http.https://github.com/.extraheader)" + git submodule sync --recursive + git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1 + + - name: Install dependencies + run: | + sudo apt-get remove -y --purge man-db # avoid time-consuming trigger + sudo add-apt-repository ppa:gjasny/iwyu + sudo apt-get update + sudo apt-get install -y clang-11 iwyu libbenchmark-dev libcurl4-openssl-dev ninja-build zlib1g-dev + + - name: "CMake Configure" + run: cmake -GNinja -DRUN_IWYU=ON -S ${{ github.workspace }} -B ${{ github.workspace }}/_build + + - name: Build + run: cmake --build ${{ github.workspace }}/_build 2>&1 | tee ${{ github.workspace }}/output.txt + + - name: Check build output + run: if egrep -q 'should (add|remove) these lines' ${{ github.workspace }}/output.txt; then exit 1; fi + + #- name: "CMake Configure" + # run: cmake -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -S ${{ github.workspace }} -B ${{ github.workspace }}/_build + + #- name: "Run IWYU" + # run: iwyu_tool -p ${{ github.workspace }}/_build core push pull -- -Xiwyu --mapping_file=${{ github.workspace }}/cmake/googletest.imp -Xiwyu --no_fwd_decls 2>&1 | tee ${{ github.workspace }}/output.txt + diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ac303a3..372e9434 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ option(ENABLE_TESTING "Build tests" ON) option(USE_THIRDPARTY_LIBRARIES "Use 3rdParty submodules" ON) option(THIRDPARTY_CIVETWEB_WITH_SSL "Enable SSL support for embedded civetweb source code") option(OVERRIDE_CXX_STANDARD_FLAGS "Force building with -std=c++11 even if the CXXLFAGS are configured differently" ON) +option(RUN_IWYU "Run include-what-you-use" OFF) if(OVERRIDE_CXX_STANDARD_FLAGS) set(CMAKE_CXX_STANDARD 11) @@ -53,6 +54,24 @@ endif() set(CMAKE_THREAD_PREFER_PTHREAD TRUE) find_package(Threads) +# include-what-you-use + +if(RUN_IWYU) + find_program(IWYU_EXECUTABLE NAMES include-what-you-use iwyu) + if(NOT IWYU_EXECUTABLE) + message(FATAL_ERROR "Include-what-you-use not found") + endif() + + set(IWYU_ARGS + "${IWYU_EXECUTABLE}" + "-Xiwyu" "--no_fwd_decls" + "-Xiwyu" "--mapping_file=${CMAKE_CURRENT_SOURCE_DIR}/cmake/googletest.imp" + ) + + set(CMAKE_C_INCLUDE_WHAT_YOU_USE ${IWYU_ARGS}) + set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE ${IWYU_ARGS}) +endif() + # check for required libatomic include(CheckAtomic) @@ -148,4 +167,5 @@ include(FeatureSummary) add_feature_info("Pull" "${ENABLE_PULL}" "support for pulling metrics") add_feature_info("Push" "${ENABLE_PUSH}" "support for pushing metrics to a push-gateway") add_feature_info("Compression" "${ENABLE_COMPRESSION}" "support for zlib compression of metrics") +add_feature_info("IYWU" "${RUN_IWYU}" "include-what-you-use") feature_summary(WHAT ALL) diff --git a/cmake/civetweb-3rdparty-config.cmake b/cmake/civetweb-3rdparty-config.cmake index d684361d..242509e5 100644 --- a/cmake/civetweb-3rdparty-config.cmake +++ b/cmake/civetweb-3rdparty-config.cmake @@ -60,3 +60,8 @@ if(BUILD_SHARED_LIBS) VISIBILITY_INLINES_HIDDEN ON ) endif() + +set_target_properties(civetweb PROPERTIES + C_INCLUDE_WHAT_YOU_USE "" + CXX_INCLUDE_WHAT_YOU_USE "" +) diff --git a/cmake/googlemock-3rdparty-config.cmake b/cmake/googlemock-3rdparty-config.cmake index c7bc4428..66defd2f 100644 --- a/cmake/googlemock-3rdparty-config.cmake +++ b/cmake/googlemock-3rdparty-config.cmake @@ -8,7 +8,7 @@ add_library(gmock_main STATIC EXCLUDE_FROM_ALL ${_IMPORT_PREFIX}/googlemock/src/gmock_main.cc ) -target_include_directories(gmock_main +target_include_directories(gmock_main SYSTEM PUBLIC ${_IMPORT_PREFIX}/googletest/include ${_IMPORT_PREFIX}/googlemock/include @@ -22,3 +22,8 @@ target_link_libraries(gmock_main Threads::Threads ) add_library(GTest::gmock_main ALIAS gmock_main) + +set_target_properties(gmock_main PROPERTIES + C_INCLUDE_WHAT_YOU_USE "" + CXX_INCLUDE_WHAT_YOU_USE "" +) diff --git a/cmake/googletest.imp b/cmake/googletest.imp new file mode 100644 index 00000000..29875d06 --- /dev/null +++ b/cmake/googletest.imp @@ -0,0 +1,4 @@ +[ + { include: [ "@", private, "", public ] }, + { include: [ "@", private, "", public ] } +] diff --git a/cmake/project-import/sample_client.cc b/cmake/project-import/sample_client.cc deleted file mode 100644 index 03414fe9..00000000 --- a/cmake/project-import/sample_client.cc +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 -#include -#else -#include -#include -#endif - -static std::string GetHostName() { - char hostname[1024]; - - if (::gethostname(hostname, sizeof(hostname))) { - return {}; - } - return hostname; -} - -int main() { - using namespace prometheus; - - // create a push gateway - const auto labels = Gateway::GetInstanceLabel(GetHostName()); - - Gateway gateway{"127.0.0.1", "9091", "sample_client", labels}; - - // create a metrics registry with component=main labels applied to all its - // metrics - auto registry = std::make_shared(); - - // add a new counter family to the registry (families combine values with the - // same name, but distinct label dimensions) - auto& counter_family = BuildCounter() - .Name("time_running_seconds_total") - .Help("How many seconds is this server running?") - .Labels({{"label", "value"}}) - .Register(*registry); - - // add a counter to the metric family - auto& second_counter = counter_family.Add( - {{"another_label", "value"}, {"yet_another_label", "value"}}); - - // ask the pusher to push the metrics to the pushgateway - gateway.RegisterCollectable(registry); - - for (;;) { - std::this_thread::sleep_for(std::chrono::seconds(1)); - // increment the counter by one (second) - second_counter.Increment(); - - // push metrics - auto returnCode = gateway.Push(); - std::cout << "returnCode is " << returnCode << std::endl; - } - return 0; -} diff --git a/cmake/project-import/sample_client.cc b/cmake/project-import/sample_client.cc new file mode 120000 index 00000000..4c67af80 --- /dev/null +++ b/cmake/project-import/sample_client.cc @@ -0,0 +1 @@ +../../push/tests/integration/sample_client.cc \ No newline at end of file diff --git a/core/benchmarks/benchmark_helpers.cc b/core/benchmarks/benchmark_helpers.cc index 8585b204..dc6ccea4 100644 --- a/core/benchmarks/benchmark_helpers.cc +++ b/core/benchmarks/benchmark_helpers.cc @@ -3,10 +3,10 @@ #include #include -std::string GenerateRandomString(size_t length) { +std::string GenerateRandomString(std::size_t length) { auto randchar = []() -> char { const char charset[] = "abcdefghijklmnopqrstuvwxyz"; - const size_t max_index = (sizeof(charset) - 1); + const std::size_t max_index = (sizeof(charset) - 1); return charset[rand() % max_index]; }; std::string str(length, 0); diff --git a/core/benchmarks/benchmark_helpers.h b/core/benchmarks/benchmark_helpers.h index 0b449a67..99cbeb03 100644 --- a/core/benchmarks/benchmark_helpers.h +++ b/core/benchmarks/benchmark_helpers.h @@ -1,8 +1,9 @@ #pragma once +#include #include #include -std::string GenerateRandomString(size_t length); +std::string GenerateRandomString(std::size_t length); std::map GenerateRandomLabels( std::size_t number_of_labels); diff --git a/core/benchmarks/counter_bench.cc b/core/benchmarks/counter_bench.cc index 3bae0557..620546f9 100644 --- a/core/benchmarks/counter_bench.cc +++ b/core/benchmarks/counter_bench.cc @@ -1,6 +1,10 @@ #include -#include -#include + +#include + +#include "prometheus/counter.h" +#include "prometheus/family.h" +#include "prometheus/registry.h" static void BM_Counter_Increment(benchmark::State& state) { using prometheus::BuildCounter; diff --git a/core/benchmarks/gauge_bench.cc b/core/benchmarks/gauge_bench.cc index d5afc492..d0c61f53 100644 --- a/core/benchmarks/gauge_bench.cc +++ b/core/benchmarks/gauge_bench.cc @@ -1,6 +1,10 @@ #include -#include -#include + +#include + +#include "prometheus/family.h" +#include "prometheus/gauge.h" +#include "prometheus/registry.h" static void BM_Gauge_Increment(benchmark::State& state) { using prometheus::BuildGauge; diff --git a/core/benchmarks/histogram_bench.cc b/core/benchmarks/histogram_bench.cc index 54458e68..64729451 100644 --- a/core/benchmarks/histogram_bench.cc +++ b/core/benchmarks/histogram_bench.cc @@ -1,9 +1,13 @@ #include -#include -#include #include #include +#include +#include + +#include "prometheus/family.h" +#include "prometheus/histogram.h" +#include "prometheus/registry.h" using prometheus::Histogram; diff --git a/core/benchmarks/registry_bench.cc b/core/benchmarks/registry_bench.cc index 67054da0..b33ddc4d 100644 --- a/core/benchmarks/registry_bench.cc +++ b/core/benchmarks/registry_bench.cc @@ -1,10 +1,11 @@ #include -#include -#include #include #include "benchmark_helpers.h" +#include "prometheus/counter.h" +#include "prometheus/family.h" +#include "prometheus/registry.h" static void BM_Registry_CreateFamily(benchmark::State& state) { using prometheus::BuildCounter; diff --git a/core/benchmarks/summary_bench.cc b/core/benchmarks/summary_bench.cc index d19c4cdc..da80811f 100644 --- a/core/benchmarks/summary_bench.cc +++ b/core/benchmarks/summary_bench.cc @@ -1,9 +1,15 @@ #include -#include -#include +#include #include +#include #include +#include +#include + +#include "prometheus/family.h" +#include "prometheus/registry.h" +#include "prometheus/summary.h" using prometheus::Summary; diff --git a/core/include/prometheus/counter.h b/core/include/prometheus/counter.h index 6ec01dd8..c67ddde2 100644 --- a/core/include/prometheus/counter.h +++ b/core/include/prometheus/counter.h @@ -1,7 +1,7 @@ #pragma once #include "prometheus/client_metric.h" -#include "prometheus/detail/builder.h" +#include "prometheus/detail/builder.h" // IWYU pragma: export #include "prometheus/detail/core_export.h" #include "prometheus/gauge.h" #include "prometheus/metric_type.h" diff --git a/core/include/prometheus/detail/builder.h b/core/include/prometheus/detail/builder.h index 0278d993..f811498f 100644 --- a/core/include/prometheus/detail/builder.h +++ b/core/include/prometheus/detail/builder.h @@ -3,11 +3,14 @@ #include #include +// IWYU pragma: private +// IWYU pragma: no_include "prometheus/family.h" + namespace prometheus { template -class Family; -class Registry; +class Family; // IWYU pragma: keep +class Registry; // IWYU pragma: keep namespace detail { diff --git a/core/include/prometheus/detail/ckms_quantiles.h b/core/include/prometheus/detail/ckms_quantiles.h index da0950fc..dad7815c 100644 --- a/core/include/prometheus/detail/ckms_quantiles.h +++ b/core/include/prometheus/detail/ckms_quantiles.h @@ -7,6 +7,8 @@ #include "prometheus/detail/core_export.h" +// IWYU pragma: private, include "prometheus/summary.h" + namespace prometheus { namespace detail { diff --git a/core/include/prometheus/detail/time_window_quantiles.h b/core/include/prometheus/detail/time_window_quantiles.h index 3a3ac65c..498baed2 100644 --- a/core/include/prometheus/detail/time_window_quantiles.h +++ b/core/include/prometheus/detail/time_window_quantiles.h @@ -4,9 +4,11 @@ #include #include -#include "prometheus/detail/ckms_quantiles.h" +#include "prometheus/detail/ckms_quantiles.h" // IWYU pragma: export #include "prometheus/detail/core_export.h" +// IWYU pragma: private, include "prometheus/summary.h" + namespace prometheus { namespace detail { diff --git a/core/include/prometheus/family.h b/core/include/prometheus/family.h index df282f12..1c333a7a 100644 --- a/core/include/prometheus/family.h +++ b/core/include/prometheus/family.h @@ -1,25 +1,24 @@ #pragma once -#include -#include #include #include #include #include -#include #include #include -#include #include -#include "prometheus/check_names.h" #include "prometheus/client_metric.h" #include "prometheus/collectable.h" #include "prometheus/detail/core_export.h" #include "prometheus/detail/future_std.h" -#include "prometheus/detail/utils.h" #include "prometheus/metric_family.h" +// IWYU pragma: no_include "prometheus/counter.h" +// IWYU pragma: no_include "prometheus/gauge.h" +// IWYU pragma: no_include "prometheus/histogram.h" +// IWYU pragma: no_include "prometheus/summary.h" + namespace prometheus { /// \brief A metric of type T with a set of labeled dimensions. diff --git a/core/include/prometheus/gauge.h b/core/include/prometheus/gauge.h index 467115b2..62498376 100644 --- a/core/include/prometheus/gauge.h +++ b/core/include/prometheus/gauge.h @@ -3,7 +3,7 @@ #include #include "prometheus/client_metric.h" -#include "prometheus/detail/builder.h" +#include "prometheus/detail/builder.h" // IWYU pragma: export #include "prometheus/detail/core_export.h" #include "prometheus/metric_type.h" diff --git a/core/include/prometheus/histogram.h b/core/include/prometheus/histogram.h index c720609a..f8be2435 100644 --- a/core/include/prometheus/histogram.h +++ b/core/include/prometheus/histogram.h @@ -4,7 +4,7 @@ #include "prometheus/client_metric.h" #include "prometheus/counter.h" -#include "prometheus/detail/builder.h" +#include "prometheus/detail/builder.h" // IWYU pragma: export #include "prometheus/detail/core_export.h" #include "prometheus/gauge.h" #include "prometheus/metric_type.h" diff --git a/core/include/prometheus/registry.h b/core/include/prometheus/registry.h index c8fdeb20..ef83438c 100644 --- a/core/include/prometheus/registry.h +++ b/core/include/prometheus/registry.h @@ -8,7 +8,6 @@ #include "prometheus/collectable.h" #include "prometheus/detail/core_export.h" -#include "prometheus/detail/future_std.h" #include "prometheus/family.h" #include "prometheus/metric_family.h" @@ -22,7 +21,7 @@ class Summary; namespace detail { template -class Builder; +class Builder; // IWYU pragma: keep } /// \brief Manages the collection of a number of metrics. diff --git a/core/include/prometheus/summary.h b/core/include/prometheus/summary.h index 7f6a4556..87381344 100644 --- a/core/include/prometheus/summary.h +++ b/core/include/prometheus/summary.h @@ -6,7 +6,7 @@ #include #include "prometheus/client_metric.h" -#include "prometheus/detail/builder.h" +#include "prometheus/detail/builder.h" // IWYU pragma: export #include "prometheus/detail/ckms_quantiles.h" #include "prometheus/detail/core_export.h" #include "prometheus/detail/time_window_quantiles.h" diff --git a/core/include/prometheus/text_serializer.h b/core/include/prometheus/text_serializer.h index b1e22c00..315a164d 100644 --- a/core/include/prometheus/text_serializer.h +++ b/core/include/prometheus/text_serializer.h @@ -1,7 +1,6 @@ #pragma once #include -#include #include #include "prometheus/detail/core_export.h" diff --git a/core/src/check_names.cc b/core/src/check_names.cc index 5a1443ae..284ec642 100644 --- a/core/src/check_names.cc +++ b/core/src/check_names.cc @@ -1,7 +1,9 @@ #include "prometheus/check_names.h" +#include #include +#include #if defined(__GLIBCXX__) && __GLIBCXX__ <= 20150623 #define STD_REGEX_IS_BROKEN diff --git a/core/src/detail/builder.cc b/core/src/detail/builder.cc index 2d82ad0d..72253834 100644 --- a/core/src/detail/builder.cc +++ b/core/src/detail/builder.cc @@ -1,6 +1,7 @@ #include "prometheus/detail/builder.h" #include "prometheus/counter.h" +#include "prometheus/detail/core_export.h" #include "prometheus/gauge.h" #include "prometheus/histogram.h" #include "prometheus/registry.h" diff --git a/core/src/detail/ckms_quantiles.cc b/core/src/detail/ckms_quantiles.cc index 63205dbc..7ab6f1f2 100644 --- a/core/src/detail/ckms_quantiles.cc +++ b/core/src/detail/ckms_quantiles.cc @@ -1,8 +1,9 @@ -#include "prometheus/detail/ckms_quantiles.h" +#include "prometheus/detail/ckms_quantiles.h" // IWYU pragma: export #include #include #include +#include namespace prometheus { namespace detail { diff --git a/core/src/detail/time_window_quantiles.cc b/core/src/detail/time_window_quantiles.cc index e767122d..57f1e1c6 100644 --- a/core/src/detail/time_window_quantiles.cc +++ b/core/src/detail/time_window_quantiles.cc @@ -1,4 +1,7 @@ -#include "prometheus/detail/time_window_quantiles.h" +#include "prometheus/detail/time_window_quantiles.h" // IWYU pragma: export + +#include +#include namespace prometheus { namespace detail { diff --git a/core/src/detail/utils.cc b/core/src/detail/utils.cc index 754ddc2d..c8b08ccb 100644 --- a/core/src/detail/utils.cc +++ b/core/src/detail/utils.cc @@ -1,6 +1,6 @@ #include "prometheus/detail/utils.h" -#include +#include #include "hash.h" diff --git a/core/src/family.cc b/core/src/family.cc index 7ed5a1dc..9d5ed362 100644 --- a/core/src/family.cc +++ b/core/src/family.cc @@ -1,8 +1,14 @@ #include "prometheus/family.h" +#include +#include #include +#include +#include +#include "prometheus/check_names.h" #include "prometheus/counter.h" +#include "prometheus/detail/utils.h" #include "prometheus/gauge.h" #include "prometheus/histogram.h" #include "prometheus/summary.h" diff --git a/core/src/histogram.cc b/core/src/histogram.cc index de2efeb0..9c05d066 100644 --- a/core/src/histogram.cc +++ b/core/src/histogram.cc @@ -4,8 +4,10 @@ #include #include #include -#include +#include #include +#include +#include namespace prometheus { diff --git a/core/src/registry.cc b/core/src/registry.cc index 7f91472e..ad565d35 100644 --- a/core/src/registry.cc +++ b/core/src/registry.cc @@ -1,8 +1,12 @@ #include "prometheus/registry.h" +#include #include +#include +#include #include "prometheus/counter.h" +#include "prometheus/detail/future_std.h" #include "prometheus/gauge.h" #include "prometheus/histogram.h" #include "prometheus/summary.h" diff --git a/core/src/serializer.cc b/core/src/serializer.cc index 4f86c455..69e6a580 100644 --- a/core/src/serializer.cc +++ b/core/src/serializer.cc @@ -1,6 +1,6 @@ #include "prometheus/serializer.h" -#include +#include // IWYU pragma: keep namespace prometheus { diff --git a/core/src/summary.cc b/core/src/summary.cc index 7ed9de61..5e309795 100644 --- a/core/src/summary.cc +++ b/core/src/summary.cc @@ -1,5 +1,7 @@ #include "prometheus/summary.h" +#include + namespace prometheus { Summary::Summary(const Quantiles& quantiles, diff --git a/core/src/text_serializer.cc b/core/src/text_serializer.cc index 858c6150..71af4ab9 100644 --- a/core/src/text_serializer.cc +++ b/core/src/text_serializer.cc @@ -5,6 +5,7 @@ #include #include #include +#include #if __cpp_lib_to_chars >= 201611L #include @@ -15,6 +16,10 @@ #include #endif +#include "prometheus/client_metric.h" +#include "prometheus/metric_family.h" +#include "prometheus/metric_type.h" + namespace prometheus { namespace { diff --git a/core/tests/builder_test.cc b/core/tests/builder_test.cc index 2bbc54c1..ce460d73 100644 --- a/core/tests/builder_test.cc +++ b/core/tests/builder_test.cc @@ -1,8 +1,17 @@ #include +#include #include - +#include +#include +#include +#include +#include +#include + +#include "prometheus/client_metric.h" #include "prometheus/counter.h" +#include "prometheus/family.h" #include "prometheus/gauge.h" #include "prometheus/histogram.h" #include "prometheus/registry.h" diff --git a/core/tests/check_names_test.cc b/core/tests/check_names_test.cc index aa6c77a9..3201c85b 100644 --- a/core/tests/check_names_test.cc +++ b/core/tests/check_names_test.cc @@ -1,6 +1,6 @@ #include "prometheus/check_names.h" -#include +#include namespace prometheus { namespace { diff --git a/core/tests/counter_test.cc b/core/tests/counter_test.cc index 1c5566cb..9087e9bd 100644 --- a/core/tests/counter_test.cc +++ b/core/tests/counter_test.cc @@ -1,6 +1,6 @@ #include "prometheus/counter.h" -#include +#include namespace prometheus { namespace { diff --git a/core/tests/family_test.cc b/core/tests/family_test.cc index d68a6a21..8da3cd64 100644 --- a/core/tests/family_test.cc +++ b/core/tests/family_test.cc @@ -1,10 +1,12 @@ #include "prometheus/family.h" #include +#include #include #include "prometheus/client_metric.h" +#include "prometheus/counter.h" #include "prometheus/detail/future_std.h" #include "prometheus/histogram.h" diff --git a/core/tests/gauge_test.cc b/core/tests/gauge_test.cc index f4f2b48a..690754b0 100644 --- a/core/tests/gauge_test.cc +++ b/core/tests/gauge_test.cc @@ -1,6 +1,6 @@ #include "prometheus/gauge.h" -#include +#include namespace prometheus { namespace { diff --git a/core/tests/histogram_test.cc b/core/tests/histogram_test.cc index 6c3b30df..86cc66a8 100644 --- a/core/tests/histogram_test.cc +++ b/core/tests/histogram_test.cc @@ -1,8 +1,10 @@ #include "prometheus/histogram.h" -#include +#include #include +#include +#include namespace prometheus { namespace { diff --git a/core/tests/registry_test.cc b/core/tests/registry_test.cc index 6a02981f..69937074 100644 --- a/core/tests/registry_test.cc +++ b/core/tests/registry_test.cc @@ -1,10 +1,12 @@ #include "prometheus/registry.h" -#include +#include +#include #include #include "prometheus/counter.h" +#include "prometheus/gauge.h" #include "prometheus/histogram.h" #include "prometheus/summary.h" diff --git a/core/tests/serializer_test.cc b/core/tests/serializer_test.cc index 528f649d..cdb5a9c5 100644 --- a/core/tests/serializer_test.cc +++ b/core/tests/serializer_test.cc @@ -1,11 +1,16 @@ #include +#include #include #include +#include +#include +#include #include "prometheus/counter.h" #include "prometheus/detail/future_std.h" #include "prometheus/family.h" +#include "prometheus/metric_family.h" #include "prometheus/text_serializer.h" #include "raii_locale.h" diff --git a/core/tests/summary_test.cc b/core/tests/summary_test.cc index 2efb4d7b..ffebd9bd 100644 --- a/core/tests/summary_test.cc +++ b/core/tests/summary_test.cc @@ -1,8 +1,10 @@ #include "prometheus/summary.h" -#include +#include #include +#include +#include #include namespace prometheus { diff --git a/core/tests/text_serializer_test.cc b/core/tests/text_serializer_test.cc index 6b9bc479..0ef68a0d 100644 --- a/core/tests/text_serializer_test.cc +++ b/core/tests/text_serializer_test.cc @@ -1,13 +1,16 @@ #include "prometheus/text_serializer.h" #include +#include #include #include +#include -#include "prometheus/family.h" -#include "prometheus/gauge.h" +#include "prometheus/client_metric.h" #include "prometheus/histogram.h" +#include "prometheus/metric_family.h" +#include "prometheus/metric_type.h" #include "prometheus/summary.h" namespace prometheus { diff --git a/core/tests/utils_test.cc b/core/tests/utils_test.cc index b1432e10..76451f65 100644 --- a/core/tests/utils_test.cc +++ b/core/tests/utils_test.cc @@ -1,8 +1,9 @@ #include "prometheus/detail/utils.h" -#include +#include #include +#include namespace prometheus { diff --git a/pull/include/prometheus/exposer.h b/pull/include/prometheus/exposer.h index e6ceb85f..3e4e01c4 100644 --- a/pull/include/prometheus/exposer.h +++ b/pull/include/prometheus/exposer.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include #include @@ -8,7 +8,6 @@ #include "prometheus/collectable.h" #include "prometheus/detail/pull_export.h" -#include "prometheus/registry.h" class CivetServer; @@ -16,7 +15,6 @@ namespace prometheus { namespace detail { class Endpoint; -class MetricsHandler; } // namespace detail class PROMETHEUS_CPP_PULL_EXPORT Exposer { diff --git a/pull/src/basic_auth.cc b/pull/src/basic_auth.cc index 7bae3ca4..a669c586 100644 --- a/pull/src/basic_auth.cc +++ b/pull/src/basic_auth.cc @@ -1,8 +1,9 @@ #include "basic_auth.h" +#include + #include "CivetServer.h" #include "detail/base64.h" -#include "prometheus/detail/future_std.h" namespace prometheus { diff --git a/pull/src/basic_auth.h b/pull/src/basic_auth.h index 87109dbf..3047b951 100644 --- a/pull/src/basic_auth.h +++ b/pull/src/basic_auth.h @@ -2,10 +2,9 @@ #include #include -#include #include "CivetServer.h" -#include "prometheus/detail/pull_export.h" +#include "civetweb.h" namespace prometheus { diff --git a/pull/src/detail/base64.h b/pull/src/detail/base64.h index 256dcc39..36233252 100644 --- a/pull/src/detail/base64.h +++ b/pull/src/detail/base64.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include diff --git a/pull/src/endpoint.cc b/pull/src/endpoint.cc index 68d42a4d..3e8ab3fb 100644 --- a/pull/src/endpoint.cc +++ b/pull/src/endpoint.cc @@ -1,5 +1,7 @@ #include "endpoint.h" +#include + #include "basic_auth.h" #include "handler.h" #include "prometheus/detail/future_std.h" diff --git a/pull/src/endpoint.h b/pull/src/endpoint.h index 2a58d847..e0605e35 100644 --- a/pull/src/endpoint.h +++ b/pull/src/endpoint.h @@ -3,14 +3,12 @@ #include #include #include -#include +#include "CivetServer.h" #include "basic_auth.h" #include "prometheus/collectable.h" #include "prometheus/registry.h" -class CivetServer; - namespace prometheus { namespace detail { class MetricsHandler; diff --git a/pull/src/exposer.cc b/pull/src/exposer.cc index b61737c0..ac53bc86 100644 --- a/pull/src/exposer.cc +++ b/pull/src/exposer.cc @@ -1,13 +1,12 @@ #include "prometheus/exposer.h" -#include +#include +#include #include -#include +#include #include "CivetServer.h" #include "endpoint.h" -#include "handler.h" -#include "prometheus/client_metric.h" #include "prometheus/detail/future_std.h" namespace prometheus { diff --git a/pull/src/handler.cc b/pull/src/handler.cc index 20a552a0..83eb19ea 100644 --- a/pull/src/handler.cc +++ b/pull/src/handler.cc @@ -1,17 +1,23 @@ #include "handler.h" #include +#include +#include #include - -#include "prometheus/counter.h" -#include "prometheus/summary.h" +#include +#include #ifdef HAVE_ZLIB +#include #include #endif +#include "civetweb.h" #include "metrics_collector.h" +#include "prometheus/counter.h" +#include "prometheus/metric_family.h" #include "prometheus/serializer.h" +#include "prometheus/summary.h" #include "prometheus/text_serializer.h" namespace prometheus { diff --git a/pull/src/handler.h b/pull/src/handler.h index 017e2a7e..10c90f9f 100644 --- a/pull/src/handler.h +++ b/pull/src/handler.h @@ -5,7 +5,9 @@ #include #include "CivetServer.h" +#include "prometheus/collectable.h" #include "prometheus/counter.h" +#include "prometheus/family.h" #include "prometheus/registry.h" #include "prometheus/summary.h" diff --git a/pull/src/metrics_collector.cc b/pull/src/metrics_collector.cc index 4235e6fd..0372d693 100644 --- a/pull/src/metrics_collector.cc +++ b/pull/src/metrics_collector.cc @@ -1,5 +1,7 @@ #include "metrics_collector.h" +#include + #include "prometheus/collectable.h" namespace prometheus { diff --git a/pull/tests/integration/integration_test.cc b/pull/tests/integration/integration_test.cc index e5832c1d..49c79176 100644 --- a/pull/tests/integration/integration_test.cc +++ b/pull/tests/integration/integration_test.cc @@ -1,13 +1,18 @@ #include #include +#include +#include #include #include +#include #include +#include #include "prometheus/counter.h" #include "prometheus/detail/future_std.h" #include "prometheus/exposer.h" +#include "prometheus/family.h" #include "prometheus/registry.h" namespace prometheus { @@ -154,7 +159,7 @@ TEST_F(IntegrationTest, acceptOptionalCompression) { EXPECT_THAT(metrics.body, HasSubstr(counter_name)); } -#if 0 // https://github.com/civetweb/civetweb/issues/954 +#if 0 // https://github.com/civetweb/civetweb/issues/954 TEST_F(IntegrationTest, shouldRejectRequestWithoutAuthorization) { const std::string counter_name = "example_total"; auto registry = RegisterSomeCounter(counter_name, default_metrics_path_); @@ -185,7 +190,8 @@ TEST_F(IntegrationTest, shouldPerformProperAuthentication) { }; exposer_->RegisterAuth( - [my_username, my_password](const std::string& user, const std::string& password) { + [my_username, my_password](const std::string& user, + const std::string& password) { return user == my_username && password == my_password; }, "Some Auth Realm", default_metrics_path_); diff --git a/pull/tests/integration/sample_server.cc b/pull/tests/integration/sample_server.cc index 55ce0163..742a365c 100644 --- a/pull/tests/integration/sample_server.cc +++ b/pull/tests/integration/sample_server.cc @@ -1,7 +1,3 @@ -#include -#include -#include - #include #include #include @@ -9,6 +5,12 @@ #include #include +#include "prometheus/client_metric.h" +#include "prometheus/counter.h" +#include "prometheus/exposer.h" +#include "prometheus/family.h" +#include "prometheus/registry.h" + int main() { using namespace prometheus; diff --git a/pull/tests/integration/sample_server_auth.cc b/pull/tests/integration/sample_server_auth.cc index 1248d55b..b8ff99dd 100644 --- a/pull/tests/integration/sample_server_auth.cc +++ b/pull/tests/integration/sample_server_auth.cc @@ -1,11 +1,14 @@ -#include -#include -#include - #include #include +#include #include +#include "prometheus/client_metric.h" +#include "prometheus/counter.h" +#include "prometheus/exposer.h" +#include "prometheus/family.h" +#include "prometheus/registry.h" + int main() { using namespace prometheus; diff --git a/pull/tests/integration/sample_server_multi.cc b/pull/tests/integration/sample_server_multi.cc index 4a86171a..9e9f41b0 100644 --- a/pull/tests/integration/sample_server_multi.cc +++ b/pull/tests/integration/sample_server_multi.cc @@ -1,11 +1,14 @@ -#include -#include -#include - #include #include +#include #include +#include "prometheus/client_metric.h" +#include "prometheus/counter.h" +#include "prometheus/exposer.h" +#include "prometheus/family.h" +#include "prometheus/registry.h" + int main() { using namespace prometheus; diff --git a/pull/tests/unit/exposer_test.cc b/pull/tests/unit/exposer_test.cc index 0c46f95b..94c2f32d 100644 --- a/pull/tests/unit/exposer_test.cc +++ b/pull/tests/unit/exposer_test.cc @@ -1,6 +1,6 @@ #include "prometheus/exposer.h" -#include +#include namespace prometheus { namespace { diff --git a/push/include/prometheus/gateway.h b/push/include/prometheus/gateway.h index 49f081c5..8e0191e3 100644 --- a/push/include/prometheus/gateway.h +++ b/push/include/prometheus/gateway.h @@ -1,14 +1,15 @@ #pragma once #include -#include #include #include +#include #include +#include #include +#include "prometheus/collectable.h" #include "prometheus/detail/push_export.h" -#include "prometheus/registry.h" namespace prometheus { diff --git a/push/src/gateway.cc b/push/src/gateway.cc index 41c0f2f5..41801909 100644 --- a/push/src/gateway.cc +++ b/push/src/gateway.cc @@ -3,15 +3,19 @@ #include +#include +#include #include #include #include -#include "prometheus/client_metric.h" #include "prometheus/detail/future_std.h" -#include "prometheus/serializer.h" +#include "prometheus/metric_family.h" // IWYU pragma: keep #include "prometheus/text_serializer.h" +// IWYU pragma: no_include +// IWYU pragma: no_include + namespace prometheus { static const char CONTENT_TYPE[] = diff --git a/push/tests/integration/sample_client.cc b/push/tests/integration/sample_client.cc index 03414fe9..d2c5f8bf 100644 --- a/push/tests/integration/sample_client.cc +++ b/push/tests/integration/sample_client.cc @@ -1,18 +1,18 @@ -#include -#include -#include - #include #include -#include #include #include #include +#include "prometheus/client_metric.h" +#include "prometheus/counter.h" +#include "prometheus/family.h" +#include "prometheus/gateway.h" +#include "prometheus/registry.h" + #ifdef _WIN32 #include #else -#include #include #endif From 5699348faa910c5decad62ea5aff41d7948d4798 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 4 Feb 2021 09:38:13 +0100 Subject: [PATCH 149/206] feat(cmake): Generate pkg-config files Fixes: #447 --- .github/workflows/cmake-ci.yml | 44 ++++++++++++++----- CMakeLists.txt | 11 +++-- .../CMakeLists.txt | 0 .../sample_client.cc | 0 .../sample_server.cc | 0 cmake/project-import-pkgconfig/CMakeLists.txt | 21 +++++++++ .../project-import-pkgconfig/sample_client.cc | 1 + .../project-import-pkgconfig/sample_server.cc | 1 + cmake/prometheus-cpp-core.pc.in | 14 ++++++ cmake/prometheus-cpp-pull.pc.in | 14 ++++++ cmake/prometheus-cpp-push.pc.in | 14 ++++++ core/CMakeLists.txt | 20 +++++++++ pull/CMakeLists.txt | 24 ++++++++++ push/CMakeLists.txt | 18 ++++++++ 14 files changed, 167 insertions(+), 15 deletions(-) rename cmake/{project-import => project-import-cmake}/CMakeLists.txt (100%) rename cmake/{project-import => project-import-cmake}/sample_client.cc (100%) rename cmake/{project-import => project-import-cmake}/sample_server.cc (100%) create mode 100644 cmake/project-import-pkgconfig/CMakeLists.txt create mode 120000 cmake/project-import-pkgconfig/sample_client.cc create mode 120000 cmake/project-import-pkgconfig/sample_server.cc create mode 100644 cmake/prometheus-cpp-core.pc.in create mode 100644 cmake/prometheus-cpp-pull.pc.in create mode 100644 cmake/prometheus-cpp-push.pc.in diff --git a/.github/workflows/cmake-ci.yml b/.github/workflows/cmake-ci.yml index 2b8c0b8f..310c3ee1 100644 --- a/.github/workflows/cmake-ci.yml +++ b/.github/workflows/cmake-ci.yml @@ -86,24 +86,44 @@ jobs: - name: "Install Release" run: cmake --install ${{ github.workspace }}/_build --config Release - - name: "Configure import for Unix with internal dependencies" + - name: "Configure CMake import for Unix with internal dependencies" if: matrix.dependencies == 'submodule' && runner.os != 'Windows' - run: cmake -Dprometheus-cpp_DIR=${{ github.workspace }}/_install/lib/cmake/prometheus-cpp -DCMAKE_CONFIGURATION_TYPES='Release;Debug' -G"Ninja Multi-Config" -S ${{ github.workspace }}/cmake/project-import -B ${{ github.workspace }}/_import + run: cmake -Dprometheus-cpp_DIR=${{ github.workspace }}/_install/lib/cmake/prometheus-cpp -DCMAKE_CONFIGURATION_TYPES='Release;Debug' -G"Ninja Multi-Config" -S ${{ github.workspace }}/cmake/project-import-cmake -B ${{ github.workspace }}/_import_cmake - - name: "Configure import for Windows with internal dependencies" + - name: "Configure CMake import for Windows with internal dependencies" if: matrix.dependencies == 'submodule' && runner.os == 'Windows' - run: cmake -Dprometheus-cpp_DIR=${{ github.workspace }}/_install/lib/cmake/prometheus-cpp -S ${{ github.workspace }}/cmake/project-import -B ${{ github.workspace }}/_import + run: cmake -Dprometheus-cpp_DIR=${{ github.workspace }}/_install/lib/cmake/prometheus-cpp -S ${{ github.workspace }}/cmake/project-import-cmake -B ${{ github.workspace }}/_import_cmake - - name: "Configure import for Unix with vcpkg dependencies" + - name: "Configure CMake import for Unix with vcpkg dependencies" if: matrix.dependencies == 'vcpkg' && runner.os != 'Windows' - run: cmake -Dprometheus-cpp_DIR=${{ github.workspace }}/_install/lib/cmake/prometheus-cpp "-DCMAKE_TOOLCHAIN_FILE=${VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake" -DCMAKE_CONFIGURATION_TYPES='Release;Debug' -G"Ninja Multi-Config" -S ${{ github.workspace }}/cmake/project-import -B ${{ github.workspace }}/_import + run: cmake -Dprometheus-cpp_DIR=${{ github.workspace }}/_install/lib/cmake/prometheus-cpp "-DCMAKE_TOOLCHAIN_FILE=${VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake" -DCMAKE_CONFIGURATION_TYPES='Release;Debug' -G"Ninja Multi-Config" -S ${{ github.workspace }}/cmake/project-import-cmake -B ${{ github.workspace }}/_import_cmake - - name: "Configure import for Windows with vcpkg dependencies" + - name: "Configure CMake import for Windows with vcpkg dependencies" if: matrix.dependencies == 'vcpkg' && runner.os == 'Windows' - run: cmake -Dprometheus-cpp_DIR=${{ github.workspace }}/_install/lib/cmake/prometheus-cpp "-DCMAKE_TOOLCHAIN_FILE=${Env:VCPKG_INSTALLATION_ROOT}\scripts\buildsystems\vcpkg.cmake" -S ${{ github.workspace }}/cmake/project-import -B ${{ github.workspace }}/_import + run: cmake -Dprometheus-cpp_DIR=${{ github.workspace }}/_install/lib/cmake/prometheus-cpp "-DCMAKE_TOOLCHAIN_FILE=${Env:VCPKG_INSTALLATION_ROOT}\scripts\buildsystems\vcpkg.cmake" -S ${{ github.workspace }}/cmake/project-import-cmake -B ${{ github.workspace }}/_import_cmake - - name: "Build import Debug" - run: cmake --build ${{ github.workspace }}/_import --config Debug + - name: "Build CMake import Debug" + run: cmake --build ${{ github.workspace }}/_import_cmake --config Debug - - name: "Build import Release" - run: cmake --build ${{ github.workspace }}/_import --config Release + - name: "Build CMake import Release" + run: cmake --build ${{ github.workspace }}/_import_cmake --config Release + + - name: "Configure for Unix Shared Libs with internal dependencies" + if: matrix.dependencies == 'submodule' && runner.os != 'Windows' + run: cmake -DUSE_THIRDPARTY_LIBRARIES=ON -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/_install_shared -DENABLE_WARNINGS_AS_ERRORS=ON -DENABLE_COMPRESSION=OFF -DENABLE_PUSH=OFF -DCMAKE_DEBUG_POSTFIX=_d -GNinja -S ${{ github.workspace }} -B ${{ github.workspace }}/_build_shared + + - name: "Build for Unix Shared Libs" + if: matrix.dependencies == 'submodule' && runner.os != 'Windows' + run: cmake --build ${{ github.workspace }}/_build_shared + + - name: "Install for Unix Shared Libs" + if: matrix.dependencies == 'submodule' && runner.os != 'Windows' + run: cmake --install ${{ github.workspace }}/_build_shared + + - name: "Configure pkg-config import for Unix" + if: matrix.dependencies == 'submodule' && runner.os != 'Windows' + run: cmake -DCMAKE_PREFIX_PATH=${{ github.workspace }}/_install_shared -GNinja -S ${{ github.workspace }}/cmake/project-import-pkgconfig -B ${{ github.workspace }}/_import_pkgconfig + + - name: "Build pkg-config import for Unix" + if: matrix.dependencies == 'submodule' && runner.os != 'Windows' + run: cmake --build ${{ github.workspace }}/_import_pkgconfig diff --git a/CMakeLists.txt b/CMakeLists.txt index 372e9434..7912dcb9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,11 @@ if(POLICY CMP0091) cmake_policy(SET CMP0091 NEW) # recognize CMAKE_MSVC_RUNTIME_LIBRARY endif() -project(prometheus-cpp VERSION 0.12.1) +project(prometheus-cpp + VERSION 0.12.1 + DESCRIPTION "Prometheus Client Library for Modern C++" + HOMEPAGE_URL "https://github.com/jupp0r/prometheus-cpp" +) include(GenerateExportHeader) include(GNUInstallDirs) @@ -20,6 +24,7 @@ option(ENABLE_TESTING "Build tests" ON) option(USE_THIRDPARTY_LIBRARIES "Use 3rdParty submodules" ON) option(THIRDPARTY_CIVETWEB_WITH_SSL "Enable SSL support for embedded civetweb source code") option(OVERRIDE_CXX_STANDARD_FLAGS "Force building with -std=c++11 even if the CXXLFAGS are configured differently" ON) +option(GENERATE_PKGCONFIG "Generate and install pkg-config files" ${UNIX}) option(RUN_IWYU "Run include-what-you-use" OFF) if(OVERRIDE_CXX_STANDARD_FLAGS) @@ -140,8 +145,7 @@ install( if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) set(CPACK_PACKAGE_CONTACT "prometheus-cpp@@noreply.github.com") - set(CPACK_PACKAGE_DESCRIPTION "C++ library for Prometheus exporters") - set(CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/jupp0r/prometheus-cpp") + set(CPACK_PACKAGE_DESCRIPTION "${PROJECT_DESCRIPTION}") set(CPACK_PACKAGE_RELOCATABLE OFF) set(CPACK_PACKAGE_VENDOR "The prometheus-cpp authors") @@ -167,5 +171,6 @@ include(FeatureSummary) add_feature_info("Pull" "${ENABLE_PULL}" "support for pulling metrics") add_feature_info("Push" "${ENABLE_PUSH}" "support for pushing metrics to a push-gateway") add_feature_info("Compression" "${ENABLE_COMPRESSION}" "support for zlib compression of metrics") +add_feature_info("pkg-config" "${GENERATE_PKGCONFIG}" "generate pkg-config files") add_feature_info("IYWU" "${RUN_IWYU}" "include-what-you-use") feature_summary(WHAT ALL) diff --git a/cmake/project-import/CMakeLists.txt b/cmake/project-import-cmake/CMakeLists.txt similarity index 100% rename from cmake/project-import/CMakeLists.txt rename to cmake/project-import-cmake/CMakeLists.txt diff --git a/cmake/project-import/sample_client.cc b/cmake/project-import-cmake/sample_client.cc similarity index 100% rename from cmake/project-import/sample_client.cc rename to cmake/project-import-cmake/sample_client.cc diff --git a/cmake/project-import/sample_server.cc b/cmake/project-import-cmake/sample_server.cc similarity index 100% rename from cmake/project-import/sample_server.cc rename to cmake/project-import-cmake/sample_server.cc diff --git a/cmake/project-import-pkgconfig/CMakeLists.txt b/cmake/project-import-pkgconfig/CMakeLists.txt new file mode 100644 index 00000000..bcd1d8e1 --- /dev/null +++ b/cmake/project-import-pkgconfig/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 3.12 FATAL_ERROR) + +project(prometheus-cpp-import) + +set(CMAKE_CXX_STANDARD 11) + +find_package(PkgConfig REQUIRED) + +pkg_check_modules(PROMETHEUS_CPP_CORE REQUIRED prometheus-cpp-core) +pkg_check_modules(PROMETHEUS_CPP_PUSH IMPORTED_TARGET prometheus-cpp-push) +pkg_check_modules(PROMETHEUS_CPP_PULL IMPORTED_TARGET prometheus-cpp-pull) + +if(PROMETHEUS_CPP_PUSH_FOUND) + add_executable(sample-client sample_client.cc) + target_link_libraries(sample-client PRIVATE PkgConfig::PROMETHEUS_CPP_PUSH) +endif() + +if(PROMETHEUS_CPP_PULL_FOUND) + add_executable(sample-server sample_server.cc) + target_link_libraries(sample-server PRIVATE PkgConfig::PROMETHEUS_CPP_PULL) +endif() diff --git a/cmake/project-import-pkgconfig/sample_client.cc b/cmake/project-import-pkgconfig/sample_client.cc new file mode 120000 index 00000000..4c67af80 --- /dev/null +++ b/cmake/project-import-pkgconfig/sample_client.cc @@ -0,0 +1 @@ +../../push/tests/integration/sample_client.cc \ No newline at end of file diff --git a/cmake/project-import-pkgconfig/sample_server.cc b/cmake/project-import-pkgconfig/sample_server.cc new file mode 120000 index 00000000..89f9e5c0 --- /dev/null +++ b/cmake/project-import-pkgconfig/sample_server.cc @@ -0,0 +1 @@ +../../pull/tests/integration/sample_server.cc \ No newline at end of file diff --git a/cmake/prometheus-cpp-core.pc.in b/cmake/prometheus-cpp-core.pc.in new file mode 100644 index 00000000..8a24ced8 --- /dev/null +++ b/cmake/prometheus-cpp-core.pc.in @@ -0,0 +1,14 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ +libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@ + +Name: @PROJECT_NAME@-core +Description: @PROJECT_DESCRIPTION@ +URL: @PROJECT_HOMEPAGE_URL@ +Version: @PROJECT_VERSION@ +Requires: +Requires.private: @PKGCONFIG_REQUIRES@ +Cflags: -I${includedir} +Libs: -L${libdir} -l@PROJECT_NAME@-core +Libs.private: @CMAKE_THREAD_LIBS_INIT@ @PKGCONFIG_LIBS@ \ No newline at end of file diff --git a/cmake/prometheus-cpp-pull.pc.in b/cmake/prometheus-cpp-pull.pc.in new file mode 100644 index 00000000..652848f6 --- /dev/null +++ b/cmake/prometheus-cpp-pull.pc.in @@ -0,0 +1,14 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ +libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@ + +Name: @PROJECT_NAME@-pull +Description: @PROJECT_DESCRIPTION@ +URL: @PROJECT_HOMEPAGE_URL@ +Version: @PROJECT_VERSION@ +Requires: @PROJECT_NAME@-core +Requires.private: @PKGCONFIG_REQUIRES@ +Cflags: -I${includedir} +Libs: -L${libdir} -l@PROJECT_NAME@-pull +Libs.private: @CMAKE_THREAD_LIBS_INIT@ @PKGCONFIG_LIBS@ diff --git a/cmake/prometheus-cpp-push.pc.in b/cmake/prometheus-cpp-push.pc.in new file mode 100644 index 00000000..a94484d1 --- /dev/null +++ b/cmake/prometheus-cpp-push.pc.in @@ -0,0 +1,14 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ +libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@ + +Name: @PROJECT_NAME@-push +Description: @PROJECT_DESCRIPTION@ +URL: @PROJECT_HOMEPAGE_URL@ +Version: @PROJECT_VERSION@ +Requires: @PROJECT_NAME@-core +Requires.private: @PKGCONFIG_REQUIRES@ +Cflags: -I${includedir} +Libs: -L${libdir} -l@PROJECT_NAME@-push +Libs.private: @CMAKE_THREAD_LIBS_INIT@ @PKGCONFIG_LIBS@ diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 11096a0b..13b27624 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -62,6 +62,26 @@ install( DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) +if(GENERATE_PKGCONFIG) + set(PKGCONFIG_LIBS) + set(PKGCONFIG_REQUIRES) + + if(HAVE_CXX_LIBATOMIC) + string(APPEND PKGCONFIG_LIBS " -latomic") + endif() + + configure_file( + ${PROJECT_SOURCE_DIR}/cmake/prometheus-cpp-core.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/prometheus-cpp-core.pc + @ONLY + ) + + install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/prometheus-cpp-core.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig + ) +endif() + if(ENABLE_TESTING) add_subdirectory(tests) endif() diff --git a/pull/CMakeLists.txt b/pull/CMakeLists.txt index 6dfa6a2f..db1452e7 100644 --- a/pull/CMakeLists.txt +++ b/pull/CMakeLists.txt @@ -85,6 +85,30 @@ install( DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) +if(GENERATE_PKGCONFIG) + set(PKGCONFIG_LIBS) + set(PKGCONFIG_REQUIRES) + + if(NOT USE_THIRDPARTY_LIBRARIES) + string(APPEND PKGCONFIG_LIBS " -lcivetweb-cpp -lcivetweb") + endif() + + if(ENABLE_COMPRESSION) + string(APPEND PKGCONFIG_REQUIRES " zlib") + endif() + + configure_file( + ${PROJECT_SOURCE_DIR}/cmake/prometheus-cpp-pull.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/prometheus-cpp-pull.pc + @ONLY + ) + + install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/prometheus-cpp-pull.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig + ) +endif() + if(ENABLE_TESTING) add_library(pull_internal_headers INTERFACE) add_library(${PROJECT_NAME}::pull_internal_headers ALIAS pull_internal_headers) diff --git a/push/CMakeLists.txt b/push/CMakeLists.txt index 81e606f1..d8690c38 100644 --- a/push/CMakeLists.txt +++ b/push/CMakeLists.txt @@ -49,6 +49,24 @@ install( DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) +if(GENERATE_PKGCONFIG) + set(PKGCONFIG_LIBS) + set(PKGCONFIG_REQUIRES) + + string(APPEND PKGCONFIG_REQUIRES " libcurl") + + configure_file( + ${PROJECT_SOURCE_DIR}/cmake/prometheus-cpp-push.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/prometheus-cpp-push.pc + @ONLY + ) + + install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/prometheus-cpp-push.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig + ) +endif() + if(ENABLE_TESTING) add_subdirectory(tests) endif() From d095854d075bbb47c27277323672c6988cf04daa Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Mon, 8 Mar 2021 20:27:26 +0100 Subject: [PATCH 150/206] ci: Add clang-format linting (#464) --- .github/workflows/linting.yml | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 557edeaa..69181bc3 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -2,7 +2,7 @@ name: Linting on: [push, pull_request] jobs: - build: + iwyu: name: Include What You Use runs-on: ubuntu-20.04 steps: @@ -38,3 +38,21 @@ jobs: #- name: "Run IWYU" # run: iwyu_tool -p ${{ github.workspace }}/_build core push pull -- -Xiwyu --mapping_file=${{ github.workspace }}/cmake/googletest.imp -Xiwyu --no_fwd_decls 2>&1 | tee ${{ github.workspace }}/output.txt + format: + name: Clang Format + runs-on: ubuntu-20.04 + steps: + - name: Checkout source + uses: actions/checkout@v2 + + - name: Install dependencies + run: | + sudo apt-get remove -y --purge man-db # avoid time-consuming trigger + sudo apt-get update + sudo apt-get install -y clang-format-11 + + - name: Run clang-format + run: find . -type f \( -name '*.c' -o -name '*.cc' -o -name '*.cpp' -o -name '*.cxx' -o -name '*.o' -o -name '*.h' -o -name '*.hpp' -o -name '*.hxx' \) -exec clang-format-11 -style=file -i {} \; + + - name: Check for changes + run: git diff --exit-code From 77b06a8709f94173c5d7141eabdf51a1349d193f Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Mon, 8 Mar 2021 20:28:04 +0100 Subject: [PATCH 151/206] core: reject duplicate label names (#463) Issue: #459 --- core/src/family.cc | 3 +++ core/tests/family_test.cc | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/core/src/family.cc b/core/src/family.cc index 9d5ed362..3fe070aa 100644 --- a/core/src/family.cc +++ b/core/src/family.cc @@ -52,6 +52,9 @@ T& Family::Add(const std::map& labels, if (!CheckLabelName(label_name)) { throw std::invalid_argument("Invalid label name"); } + if (constant_labels_.count(label_name)) { + throw std::invalid_argument("Duplicate label name"); + } } auto metric = metrics_.insert(std::make_pair(hash, std::move(object))); diff --git a/core/tests/family_test.cc b/core/tests/family_test.cc index 8da3cd64..5d43fefc 100644 --- a/core/tests/family_test.cc +++ b/core/tests/family_test.cc @@ -28,6 +28,13 @@ TEST(FamilyTest, labels) { ::testing::ElementsAre(const_label, dynamic_label)); } +TEST(FamilyTest, reject_same_label_keys) { + auto labels = std::map{{"component", "test"}}; + + Family family{"total_requests", "Counts all requests", labels}; + EXPECT_ANY_THROW(family.Add(labels)); +} + TEST(FamilyTest, counter_value) { Family family{"total_requests", "Counts all requests", {}}; auto& counter = family.Add({}); From 1d36d42210bc57cfc0b4ccdc87ff2cee44669de7 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Mon, 8 Mar 2021 20:29:25 +0100 Subject: [PATCH 152/206] core: Replace name check regex (#462) * core: test for more invalid lables * core: rewrite label and metric name checks The std::regex has the problem that it is not available everywhere and also it's 75 times slower than the naive validity check. ``` BM_Label_Check_Regex 550 ns 550 ns 1270601 BM_Label_Check_NoRegex 7.50 ns 7.50 ns 92802503 ``` --- core/src/check_names.cc | 94 ++++++++++++++++++++++++---------- core/tests/check_names_test.cc | 9 ++++ 2 files changed, 76 insertions(+), 27 deletions(-) diff --git a/core/src/check_names.cc b/core/src/check_names.cc index 284ec642..8ce018af 100644 --- a/core/src/check_names.cc +++ b/core/src/check_names.cc @@ -1,39 +1,79 @@ #include "prometheus/check_names.h" -#include -#include -#include - -#if defined(__GLIBCXX__) && __GLIBCXX__ <= 20150623 -#define STD_REGEX_IS_BROKEN -#endif -#if defined(_MSC_VER) && _MSC_VER < 1900 -#define STD_REGEX_IS_BROKEN -#endif +#include +#include namespace prometheus { -bool CheckMetricName(const std::string& name) { - // see https://prometheus.io/docs/concepts/data_model/ + +namespace { +bool isLocaleIndependentAlphaNumeric(char c) { + return ('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || + ('A' <= c && c <= 'Z'); +} + +bool isLocaleIndependentDigit(char c) { return '0' <= c && c <= '9'; } + +bool nameStartsValid(const std::string& name) { + // must not be empty + if (name.empty()) { + return false; + } + + // must not start with a digit + if (isLocaleIndependentDigit(name.front())) { + return false; + } + + // must not start with "__" auto reserved_for_internal_purposes = name.compare(0, 2, "__") == 0; if (reserved_for_internal_purposes) return false; -#ifdef STD_REGEX_IS_BROKEN - return !name.empty(); -#else - static const std::regex metric_name_regex("[a-zA-Z_:][a-zA-Z0-9_:]*"); - return std::regex_match(name, metric_name_regex); -#endif + + return true; } +} // anonymous namespace +/// \brief Check if the metric name is valid +/// +/// The metric name regex is "[a-zA-Z_:][a-zA-Z0-9_:]*" +/// +/// \see https://prometheus.io/docs/concepts/data_model/ +/// +/// \param name metric name +/// \return true is valid, false otherwise +bool CheckMetricName(const std::string& name) { + if (!nameStartsValid(name)) { + return false; + } + + auto validMetricCharacters = [](char c) { + return isLocaleIndependentAlphaNumeric(c) || c == '_' || c == ':'; + }; + + auto mismatch = + std::find_if_not(std::begin(name), std::end(name), validMetricCharacters); + return mismatch == std::end(name); +} + +/// \brief Check if the label name is valid +/// +/// The label name regex is "[a-zA-Z_][a-zA-Z0-9_]*" +/// +/// \see https://prometheus.io/docs/concepts/data_model/ +/// +/// \param name label name +/// \return true is valid, false otherwise bool CheckLabelName(const std::string& name) { - // see https://prometheus.io/docs/concepts/data_model/ - auto reserved_for_internal_purposes = name.compare(0, 2, "__") == 0; - if (reserved_for_internal_purposes) return false; -#ifdef STD_REGEX_IS_BROKEN - return !name.empty(); -#else - static const std::regex label_name_regex("[a-zA-Z_][a-zA-Z0-9_]*"); - return std::regex_match(name, label_name_regex); -#endif + if (!nameStartsValid(name)) { + return false; + } + + auto validLabelCharacters = [](char c) { + return isLocaleIndependentAlphaNumeric(c) || c == '_'; + }; + + auto mismatch = + std::find_if_not(std::begin(name), std::end(name), validLabelCharacters); + return mismatch == std::end(name); } } // namespace prometheus diff --git a/core/tests/check_names_test.cc b/core/tests/check_names_test.cc index 3201c85b..d4f1848b 100644 --- a/core/tests/check_names_test.cc +++ b/core/tests/check_names_test.cc @@ -16,6 +16,15 @@ TEST(CheckNamesTest, malformed_metric_name) { EXPECT_FALSE(CheckMetricName("fa mi ly with space in name or |")); } TEST(CheckNamesTest, empty_label_name) { EXPECT_FALSE(CheckLabelName("")); } +TEST(CheckNamesTest, invalid_label_name) { + EXPECT_FALSE(CheckLabelName("log-level")); +} +TEST(CheckNamesTest, leading_invalid_label_name) { + EXPECT_FALSE(CheckLabelName("-abcd")); +} +TEST(CheckNamesTest, trailing_invalid_label_name) { + EXPECT_FALSE(CheckLabelName("abcd-")); +} TEST(CheckNamesTest, good_label_name) { EXPECT_TRUE(CheckLabelName("type")); } TEST(CheckNamesTest, reserved_label_name) { EXPECT_FALSE(CheckMetricName("__some_reserved_label")); From fdb1a744be76418305916fd10a0e7564b4486afd Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Tue, 9 Mar 2021 11:14:34 +0100 Subject: [PATCH 153/206] chore: prepare prometheus-cpp 0.12.2 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7912dcb9..4b9dcdaf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ if(POLICY CMP0091) endif() project(prometheus-cpp - VERSION 0.12.1 + VERSION 0.12.2 DESCRIPTION "Prometheus Client Library for Modern C++" HOMEPAGE_URL "https://github.com/jupp0r/prometheus-cpp" ) From 5b465a4e6c995cea61346b16d70afa71e0a3b2aa Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Tue, 9 Mar 2021 10:29:53 +0100 Subject: [PATCH 154/206] pull: Announce utf-8 content encoding Closes: #377 --- pull/src/handler.cc | 2 +- pull/tests/integration/integration_test.cc | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/pull/src/handler.cc b/pull/src/handler.cc index 83eb19ea..cec37f33 100644 --- a/pull/src/handler.cc +++ b/pull/src/handler.cc @@ -96,7 +96,7 @@ static std::size_t WriteResponse(struct mg_connection* conn, const std::string& body) { mg_printf(conn, "HTTP/1.1 200 OK\r\n" - "Content-Type: text/plain\r\n"); + "Content-Type: text/plain; charset=utf-8\r\n"); #ifdef HAVE_ZLIB auto acceptsGzip = IsEncodingAccepted(conn, "gzip"); diff --git a/pull/tests/integration/integration_test.cc b/pull/tests/integration/integration_test.cc index 49c79176..0ac4fd99 100644 --- a/pull/tests/integration/integration_test.cc +++ b/pull/tests/integration/integration_test.cc @@ -31,6 +31,7 @@ class IntegrationTest : public testing::Test { struct Resonse { long code = 0; std::string body; + std::string contentType; }; std::function fetchPrePerform_; @@ -59,6 +60,12 @@ class IntegrationTest : public testing::Test { curl_easy_getinfo(curl.get(), CURLINFO_RESPONSE_CODE, &response.code); + char* ct = nullptr; + curl_easy_getinfo(curl.get(), CURLINFO_CONTENT_TYPE, &ct); + if (ct) { + response.contentType = ct; + } + return response; } @@ -225,5 +232,17 @@ TEST_F(IntegrationTest, shouldDealWithExpiredCollectables) { EXPECT_THAT(metrics.body, Not(HasSubstr(second_counter_name))); } +TEST_F(IntegrationTest, shouldSendBodyAsUtf8) { + const std::string counter_name = "example_total"; + auto registry = RegisterSomeCounter(counter_name, default_metrics_path_); + + const auto metrics = FetchMetrics(default_metrics_path_); + + // check content type + + ASSERT_EQ(metrics.code, 200); + EXPECT_THAT(metrics.contentType, HasSubstr("utf-8")); +} + } // namespace } // namespace prometheus From 2412990ee9ad89245e7d1df9ec85ab19b24674d3 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Tue, 9 Mar 2021 11:12:10 +0100 Subject: [PATCH 155/206] core: avoid collecting empty metric families --- core/src/family.cc | 6 +++++- core/tests/family_test.cc | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/core/src/family.cc b/core/src/family.cc index 3fe070aa..b78f3619 100644 --- a/core/src/family.cc +++ b/core/src/family.cc @@ -3,7 +3,6 @@ #include #include #include -#include #include #include "prometheus/check_names.h" @@ -90,6 +89,11 @@ const std::map Family::GetConstantLabels() const { template std::vector Family::Collect() const { std::lock_guard lock{mutex_}; + + if (metrics_.empty()) { + return {}; + } + auto family = MetricFamily{}; family.name = name_; family.help = help_; diff --git a/core/tests/family_test.cc b/core/tests/family_test.cc index 5d43fefc..ddbe9839 100644 --- a/core/tests/family_test.cc +++ b/core/tests/family_test.cc @@ -103,5 +103,11 @@ TEST(FamilyTest, should_throw_on_invalid_labels) { EXPECT_ANY_THROW(add_metric_with_invalid_label_name()); } +TEST(FamilyTest, should_not_collect_empty_metrics) { + Family family{"total_requests", "Counts all requests", {}}; + auto collected = family.Collect(); + EXPECT_TRUE(collected.empty()); +} + } // namespace } // namespace prometheus From a1c9b1dc4685522291c59934f3bd8b0ffbb3fdc1 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 21 Mar 2021 18:12:39 +0100 Subject: [PATCH 156/206] push: Always use POST (regardless of body presence) Fixes: #469 --- push/src/gateway.cc | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/push/src/gateway.cc b/push/src/gateway.cc index 41801909..2f644eac 100644 --- a/push/src/gateway.cc +++ b/push/src/gateway.cc @@ -94,11 +94,10 @@ int Gateway::performHttpRequest(HttpMethod method, const std::string& uri, curl_easy_setopt(curl, CURLOPT_URL, uri.c_str()); curl_slist* header_chunk = nullptr; + header_chunk = curl_slist_append(header_chunk, CONTENT_TYPE); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_chunk); if (!body.empty()) { - header_chunk = curl_slist_append(header_chunk, CONTENT_TYPE); - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_chunk); - curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.size()); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.data()); } @@ -110,8 +109,7 @@ int Gateway::performHttpRequest(HttpMethod method, const std::string& uri, switch (method) { case HttpMethod::Post: - curl_easy_setopt(curl, CURLOPT_HTTPGET, 0L); - curl_easy_setopt(curl, CURLOPT_NOBODY, 0L); + curl_easy_setopt(curl, CURLOPT_POST, 1L); break; case HttpMethod::Put: From d3875d209d831a2e3db5c0e9439cc73ad141804b Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Wed, 7 Apr 2021 01:01:25 +0200 Subject: [PATCH 157/206] chore: use curl 7.76.0 --- bazel/repositories.bzl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index fe35ee0b..f954bb61 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -26,11 +26,11 @@ def prometheus_cpp_repositories(): maybe( http_archive, name = "com_github_curl", - sha256 = "ba98332752257b47b9dea6d8c0ad25ec1745c20424f1dd3ff2c99ab59e97cf91", - strip_prefix = "curl-7.73.0", + sha256 = "3b4378156ba09e224008e81dcce854b7ce4d182b1f9cfb97fe5ed9e9c18c6bd3", + strip_prefix = "curl-7.76.0", urls = [ - "https://github.com/curl/curl/releases/download/curl-7_73_0/curl-7.73.0.tar.gz", - "https://curl.haxx.se/download/curl-7.73.0.tar.gz", + "https://github.com/curl/curl/releases/download/curl-7_76_0/curl-7.76.0.tar.gz", + "https://curl.haxx.se/download/curl-7.76.0.tar.gz", ], build_file = "@com_github_jupp0r_prometheus_cpp//bazel:curl.BUILD", ) From 76a3ebfc35d871c7aae71e0e7d9b64e1a3bd58ba Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Wed, 7 Apr 2021 01:02:59 +0200 Subject: [PATCH 158/206] chore: use civetweb 1.14 --- 3rdparty/civetweb | 2 +- bazel/repositories.bzl | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/3rdparty/civetweb b/3rdparty/civetweb index 8e243456..c1d08d3c 160000 --- a/3rdparty/civetweb +++ b/3rdparty/civetweb @@ -1 +1 @@ -Subproject commit 8e243456965c9be5212cb96519da69cd54550e3d +Subproject commit c1d08d3c35bc939da7bec09973bda77c702c1d00 diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index f954bb61..387efc1c 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -5,10 +5,10 @@ def prometheus_cpp_repositories(): maybe( http_archive, name = "civetweb", - strip_prefix = "civetweb-1.13", - sha256 = "a7ccc76c2f1b5f4e8d855eb328ed542f8fe3b882a6da868781799a98f4acdedc", + strip_prefix = "civetweb-1.14", + sha256 = "d02d7ab091c8b4edf21fc13a03c6db08a8a8b8605e35e0073251b9d88443c653", urls = [ - "https://github.com/civetweb/civetweb/archive/v1.13.tar.gz", + "https://github.com/civetweb/civetweb/archive/v1.14.tar.gz", ], build_file = "@com_github_jupp0r_prometheus_cpp//bazel:civetweb.BUILD", ) From 8416888625b76922d633eb63162f7e433040f0bc Mon Sep 17 00:00:00 2001 From: kuvaldini Date: Sat, 1 May 2021 20:54:48 +0300 Subject: [PATCH 159/206] Add CivetCallbacks to Exposer ctor This change adds customizability to the embedded civetweb server by passing through a callbacks struct. This can be used to customize logging, etc. Signed-off-by: kuvaldini closes #479 --- pull/include/prometheus/exposer.h | 7 +++++-- pull/src/exposer.cc | 16 ++++++++++------ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/pull/include/prometheus/exposer.h b/pull/include/prometheus/exposer.h index 3e4e01c4..793225a5 100644 --- a/pull/include/prometheus/exposer.h +++ b/pull/include/prometheus/exposer.h @@ -10,6 +10,7 @@ #include "prometheus/detail/pull_export.h" class CivetServer; +struct CivetCallbacks; namespace prometheus { @@ -20,8 +21,10 @@ class Endpoint; class PROMETHEUS_CPP_PULL_EXPORT Exposer { public: explicit Exposer(const std::string& bind_address, - const std::size_t num_threads = 2); - explicit Exposer(std::vector options); + const std::size_t num_threads = 2, + const CivetCallbacks* callbacks = nullptr); + explicit Exposer(std::vector options, + const CivetCallbacks* callbacks = nullptr); ~Exposer(); void RegisterCollectable(const std::weak_ptr& collectable, const std::string& uri = std::string("/metrics")); diff --git a/pull/src/exposer.cc b/pull/src/exposer.cc index ac53bc86..546c9bc1 100644 --- a/pull/src/exposer.cc +++ b/pull/src/exposer.cc @@ -11,13 +11,17 @@ namespace prometheus { -Exposer::Exposer(const std::string& bind_address, const std::size_t num_threads) - : Exposer(std::vector{"listening_ports", bind_address, - "num_threads", - std::to_string(num_threads)}) {} +Exposer::Exposer(const std::string& bind_address, const std::size_t num_threads, + const CivetCallbacks* callbacks) + : Exposer( + std::vector{"listening_ports", bind_address, + "num_threads", std::to_string(num_threads)}, + callbacks) {} -Exposer::Exposer(std::vector options) - : server_(detail::make_unique(std::move(options))) {} +Exposer::Exposer(std::vector options, + const CivetCallbacks* callbacks) + : server_(detail::make_unique(std::move(options), callbacks)) { +} Exposer::~Exposer() = default; From 1e00fd60434448fdb306c5f2e03051a01be3cdd9 Mon Sep 17 00:00:00 2001 From: Sebastian Woetzel Date: Mon, 3 May 2021 16:11:47 +0200 Subject: [PATCH 160/206] core: add method to query family if metric exists (#482) If metrics are dynamically added and removed to and from a family in a RAAI way, there must only be only owner of the reference returned by the family.Add method. To allow this we need to know if a metric with specific labels already exist within the family. Co-authored-by: Sebastian Woetzel --- core/include/prometheus/family.h | 5 +++++ core/src/family.cc | 7 +++++++ core/tests/family_test.cc | 7 +++++++ 3 files changed, 19 insertions(+) diff --git a/core/include/prometheus/family.h b/core/include/prometheus/family.h index 1c333a7a..93ed021c 100644 --- a/core/include/prometheus/family.h +++ b/core/include/prometheus/family.h @@ -119,6 +119,11 @@ class PROMETHEUS_CPP_CORE_EXPORT Family : public Collectable { /// if the given metric was not returned by Add(). void Remove(T* metric); + /// \brief Returns true if the dimensional data with the given labels exist + /// + /// \param labels A set of key-value pairs (= labels) of the dimensional data. + bool Has(const std::map& labels) const; + /// \brief Returns the name for this family. /// /// \return The family name. diff --git a/core/src/family.cc b/core/src/family.cc index b78f3619..82d73c62 100644 --- a/core/src/family.cc +++ b/core/src/family.cc @@ -76,6 +76,13 @@ void Family::Remove(T* metric) { labels_reverse_lookup_.erase(metric); } +template +bool Family::Has(const std::map& labels) const { + auto hash = detail::hash_labels(labels); + std::lock_guard lock{mutex_}; + return metrics_.find(hash) != metrics_.end(); +} + template const std::string& Family::GetName() const { return name_; diff --git a/core/tests/family_test.cc b/core/tests/family_test.cc index ddbe9839..37f6d139 100644 --- a/core/tests/family_test.cc +++ b/core/tests/family_test.cc @@ -109,5 +109,12 @@ TEST(FamilyTest, should_not_collect_empty_metrics) { EXPECT_TRUE(collected.empty()); } +TEST(FamilyTest, query_family_if_metric_already_exists) { + Family family{"total_rquests", "Counts all requests", {}}; + family.Add({{"name", "counter1"}}); + EXPECT_TRUE(family.Has({{"name", "counter1"}})); + EXPECT_FALSE(family.Has({{"name", "couner2"}})); +} + } // namespace } // namespace prometheus From 736f73404913749c2a0bdf70674190469971bc46 Mon Sep 17 00:00:00 2001 From: Andrew Maier Date: Fri, 7 May 2021 14:46:03 -0600 Subject: [PATCH 161/206] CMakeLists: Change cmake min version to 3.14 For cmake versions older than 3.14, the cpack generation fails at the top level directory with the following: CMake Error: The source directory "" does not exist. Specify --help for usage, or press the help button on the CMake GUI. Using cmake 3.14 or newer fixes this. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b9dcdaf..7c2ef1d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ -cmake_minimum_required(VERSION 3.12 FATAL_ERROR) +cmake_minimum_required(VERSION 3.14 FATAL_ERROR) if(POLICY CMP0091) cmake_policy(SET CMP0091 NEW) # recognize CMAKE_MSVC_RUNTIME_LIBRARY endif() From 8e74a80e501889343fae23177cd4a4bb0af16b91 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 9 May 2021 18:40:34 +0200 Subject: [PATCH 162/206] pull: Prevent ABI break due to #479 --- pull/include/prometheus/exposer.h | 14 +++++++++++--- pull/src/exposer.cc | 6 ++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/pull/include/prometheus/exposer.h b/pull/include/prometheus/exposer.h index 793225a5..85804f04 100644 --- a/pull/include/prometheus/exposer.h +++ b/pull/include/prometheus/exposer.h @@ -20,11 +20,19 @@ class Endpoint; class PROMETHEUS_CPP_PULL_EXPORT Exposer { public: + /// @note This ctor will be merged with the "callback" variant once + /// prometheus-cpp 0.13 performs an ABI-break explicit Exposer(const std::string& bind_address, - const std::size_t num_threads = 2, - const CivetCallbacks* callbacks = nullptr); + const std::size_t num_threads = 2); + /// @note This ctor will be merged with the "callback" variant once + /// prometheus-cpp 0.13 performs an ABI-break + explicit Exposer(std::vector options); + + explicit Exposer(const std::string& bind_address, + const std::size_t num_threads, + const CivetCallbacks* callbacks); explicit Exposer(std::vector options, - const CivetCallbacks* callbacks = nullptr); + const CivetCallbacks* callbacks); ~Exposer(); void RegisterCollectable(const std::weak_ptr& collectable, const std::string& uri = std::string("/metrics")); diff --git a/pull/src/exposer.cc b/pull/src/exposer.cc index 546c9bc1..f278bbb9 100644 --- a/pull/src/exposer.cc +++ b/pull/src/exposer.cc @@ -11,6 +11,12 @@ namespace prometheus { +Exposer::Exposer(const std::string& bind_address, const std::size_t num_threads) + : Exposer(bind_address, num_threads, nullptr) {} + +Exposer::Exposer(std::vector options) + : Exposer(options, nullptr) {} + Exposer::Exposer(const std::string& bind_address, const std::size_t num_threads, const CivetCallbacks* callbacks) : Exposer( From 839379bda90c17263ecc5216ea9a5bceac4d2ca9 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 9 May 2021 18:58:26 +0200 Subject: [PATCH 163/206] chore: use curl 7.76.1 --- bazel/repositories.bzl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index 387efc1c..c7ad0e27 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -26,11 +26,11 @@ def prometheus_cpp_repositories(): maybe( http_archive, name = "com_github_curl", - sha256 = "3b4378156ba09e224008e81dcce854b7ce4d182b1f9cfb97fe5ed9e9c18c6bd3", - strip_prefix = "curl-7.76.0", + sha256 = "5f85c4d891ccb14d6c3c701da3010c91c6570c3419391d485d95235253d837d7", + strip_prefix = "curl-7.76.1", urls = [ - "https://github.com/curl/curl/releases/download/curl-7_76_0/curl-7.76.0.tar.gz", - "https://curl.haxx.se/download/curl-7.76.0.tar.gz", + "https://github.com/curl/curl/releases/download/curl-7_76_1/curl-7.76.1.tar.gz", + "https://curl.haxx.se/download/curl-7.76.1.tar.gz", ], build_file = "@com_github_jupp0r_prometheus_cpp//bazel:curl.BUILD", ) @@ -39,7 +39,7 @@ def prometheus_cpp_repositories(): http_archive, name = "com_github_google_benchmark", sha256 = "dccbdab796baa1043f04982147e67bb6e118fe610da2c65f88912d73987e700c", - strip_prefix = "benchmark-1.5.2", + strip_prefix = "benchmark-1.5.3", urls = [ "https://github.com/google/benchmark/archive/v1.5.2.tar.gz", ], From 37d7a5cdfd91280cc6f8f70cff2b6e06fb173f39 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 9 May 2021 18:59:18 +0200 Subject: [PATCH 164/206] chore: use google benchmark 1.5.3 --- bazel/repositories.bzl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index c7ad0e27..c2d75300 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -38,10 +38,10 @@ def prometheus_cpp_repositories(): maybe( http_archive, name = "com_github_google_benchmark", - sha256 = "dccbdab796baa1043f04982147e67bb6e118fe610da2c65f88912d73987e700c", + sha256 = "e4fbb85eec69e6668ad397ec71a3a3ab165903abe98a8327db920b94508f720e", strip_prefix = "benchmark-1.5.3", urls = [ - "https://github.com/google/benchmark/archive/v1.5.2.tar.gz", + "https://github.com/google/benchmark/archive/v1.5.3.tar.gz", ], ) From 3d24cf1e9687f248767c3a736ab1b35fa07999ef Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 9 May 2021 19:25:23 +0200 Subject: [PATCH 165/206] pull: Install header files for embedded civetweb Fixes: #479 --- cmake/civetweb-3rdparty-config.cmake | 5 +++++ pull/CMakeLists.txt | 2 ++ 2 files changed, 7 insertions(+) diff --git a/cmake/civetweb-3rdparty-config.cmake b/cmake/civetweb-3rdparty-config.cmake index 242509e5..642226e3 100644 --- a/cmake/civetweb-3rdparty-config.cmake +++ b/cmake/civetweb-3rdparty-config.cmake @@ -19,6 +19,11 @@ add_library(civetweb OBJECT ${_IMPORT_PREFIX}/src/md5.inl ) +set_property(TARGET civetweb PROPERTY PUBLIC_HEADER + ${_IMPORT_PREFIX}/include/CivetServer.h + ${_IMPORT_PREFIX}/include/civetweb.h +) + target_compile_definitions(civetweb PRIVATE CIVETWEB_API= diff --git a/pull/CMakeLists.txt b/pull/CMakeLists.txt index db1452e7..250128d7 100644 --- a/pull/CMakeLists.txt +++ b/pull/CMakeLists.txt @@ -4,6 +4,8 @@ if(USE_THIRDPARTY_LIBRARIES) install( TARGETS civetweb EXPORT ${PROJECT_NAME}-targets + # keep embedded civetweb headers scoped to prometheus(-cpp) + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/prometheus ) else() find_package(civetweb CONFIG REQUIRED) From 84388828ae80556f57e11249dbd0063043991fb4 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 9 May 2021 18:54:35 +0200 Subject: [PATCH 166/206] Prepare v0.12.3 release --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c2ef1d3..9d803bac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ if(POLICY CMP0091) endif() project(prometheus-cpp - VERSION 0.12.2 + VERSION 0.12.3 DESCRIPTION "Prometheus Client Library for Modern C++" HOMEPAGE_URL "https://github.com/jupp0r/prometheus-cpp" ) From 7ebc0d2f960a90c9969b96ecdfb9285383763817 Mon Sep 17 00:00:00 2001 From: Pave Pimenov Date: Sat, 1 May 2021 13:17:05 +0300 Subject: [PATCH 167/206] fix make_unique --- pull/src/handler.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pull/src/handler.cc b/pull/src/handler.cc index cec37f33..b437c1fd 100644 --- a/pull/src/handler.cc +++ b/pull/src/handler.cc @@ -151,7 +151,7 @@ bool MetricsHandler::handleGet(CivetServer*, struct mg_connection* conn) { metrics = CollectMetrics(collectables_); } - auto serializer = std::unique_ptr{new TextSerializer()}; + auto serializer = detail::make_unique(); auto bodySize = WriteResponse(conn, serializer->Serialize(metrics)); From 91c4d5acf059f0b9d574ccd865a729620c76eeed Mon Sep 17 00:00:00 2001 From: Pavel Pimenov Date: Sat, 8 May 2021 14:57:51 +0300 Subject: [PATCH 168/206] Update handler.cc --- pull/src/handler.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pull/src/handler.cc b/pull/src/handler.cc index b437c1fd..c0294ae9 100644 --- a/pull/src/handler.cc +++ b/pull/src/handler.cc @@ -151,9 +151,9 @@ bool MetricsHandler::handleGet(CivetServer*, struct mg_connection* conn) { metrics = CollectMetrics(collectables_); } - auto serializer = detail::make_unique(); + const TextSerializer serializer; - auto bodySize = WriteResponse(conn, serializer->Serialize(metrics)); + auto bodySize = WriteResponse(conn, serializer.Serialize(metrics)); auto stop_time_of_request = std::chrono::steady_clock::now(); auto duration = std::chrono::duration_cast( From 722d8d093613af7d677f7f2fa7bde37f946b7cd8 Mon Sep 17 00:00:00 2001 From: Pavel Pimenov Date: Sun, 9 May 2021 22:20:55 +0300 Subject: [PATCH 169/206] Update handler.cc remove #include "prometheus/serializer.h" --- pull/src/handler.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/pull/src/handler.cc b/pull/src/handler.cc index c0294ae9..da8f7055 100644 --- a/pull/src/handler.cc +++ b/pull/src/handler.cc @@ -16,7 +16,6 @@ #include "metrics_collector.h" #include "prometheus/counter.h" #include "prometheus/metric_family.h" -#include "prometheus/serializer.h" #include "prometheus/summary.h" #include "prometheus/text_serializer.h" From 5522e6f89ecd7bad72a0af415e5d0e199ff0b8d1 Mon Sep 17 00:00:00 2001 From: Jupp Mueller Date: Fri, 14 May 2021 14:18:23 -0700 Subject: [PATCH 170/206] Make summary quantiles non-const (#493) This change removes an unnecessary API constraint that makes it harder to dynamically construct quantile configurations for summaries. Fixes #425 --- cmake/googletest.imp | 3 ++- core/include/prometheus/detail/ckms_quantiles.h | 16 ++++++++-------- core/tests/summary_test.cc | 9 +++++++++ 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/cmake/googletest.imp b/cmake/googletest.imp index 29875d06..c23b9f06 100644 --- a/cmake/googletest.imp +++ b/cmake/googletest.imp @@ -1,4 +1,5 @@ [ { include: [ "@", private, "", public ] }, - { include: [ "@", private, "", public ] } + { include: [ "@", private, "", public ] }, + { include: [ "@", private, "", public ]} ] diff --git a/core/include/prometheus/detail/ckms_quantiles.h b/core/include/prometheus/detail/ckms_quantiles.h index dad7815c..771e816f 100644 --- a/core/include/prometheus/detail/ckms_quantiles.h +++ b/core/include/prometheus/detail/ckms_quantiles.h @@ -15,21 +15,21 @@ namespace detail { class PROMETHEUS_CPP_CORE_EXPORT CKMSQuantiles { public: struct PROMETHEUS_CPP_CORE_EXPORT Quantile { - const double quantile; - const double error; - const double u; - const double v; - Quantile(double quantile, double error); + + double quantile; + double error; + double u; + double v; }; private: struct Item { - /*const*/ double value; + double value; int g; - /*const*/ int delta; + int delta; - explicit Item(double value, int lower_delta, int delta); + Item(double value, int lower_delta, int delta); }; public: diff --git a/core/tests/summary_test.cc b/core/tests/summary_test.cc index ffebd9bd..4b28bc26 100644 --- a/core/tests/summary_test.cc +++ b/core/tests/summary_test.cc @@ -2,6 +2,7 @@ #include +#include #include #include #include @@ -92,5 +93,13 @@ TEST(SummaryTest, max_age) { test_value(std::numeric_limits::quiet_NaN()); } +TEST(SummaryTest, construction_with_dynamic_quantile_vector) { + auto quantiles = Summary::Quantiles{{0.99, 0.001}}; + quantiles.push_back({0.5, 0.05}); + + Summary summary{quantiles, std::chrono::seconds(1), 2}; + summary.Observe(8.0); +} + } // namespace } // namespace prometheus From 2ef7d1f893b6e55bc93843df626954c0d31de397 Mon Sep 17 00:00:00 2001 From: Pavel Pimenov Date: Sat, 15 May 2021 18:02:41 +0300 Subject: [PATCH 171/206] Add const/reserve (#495) Co-authored-by: pavel pimenov --- core/src/family.cc | 13 +++++++------ core/src/histogram.cc | 1 + core/src/summary.cc | 1 + 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/core/src/family.cc b/core/src/family.cc index 82d73c62..eb2b1e3e 100644 --- a/core/src/family.cc +++ b/core/src/family.cc @@ -32,7 +32,7 @@ Family::Family(const std::string& name, const std::string& help, template T& Family::Add(const std::map& labels, std::unique_ptr object) { - auto hash = detail::hash_labels(labels); + const auto hash = detail::hash_labels(labels); std::lock_guard lock{mutex_}; auto metrics_iter = metrics_.find(hash); @@ -47,7 +47,7 @@ T& Family::Add(const std::map& labels, } for (auto& label_pair : labels) { - auto& label_name = label_pair.first; + const auto& label_name = label_pair.first; if (!CheckLabelName(label_name)) { throw std::invalid_argument("Invalid label name"); } @@ -56,7 +56,7 @@ T& Family::Add(const std::map& labels, } } - auto metric = metrics_.insert(std::make_pair(hash, std::move(object))); + const auto metric = metrics_.insert(std::make_pair(hash, std::move(object))); assert(metric.second); labels_.insert({hash, labels}); labels_reverse_lookup_.insert({metric.first->second.get(), hash}); @@ -70,7 +70,7 @@ void Family::Remove(T* metric) { return; } - auto hash = labels_reverse_lookup_.at(metric); + const auto hash = labels_reverse_lookup_.at(metric); metrics_.erase(hash); labels_.erase(hash); labels_reverse_lookup_.erase(metric); @@ -78,7 +78,7 @@ void Family::Remove(T* metric) { template bool Family::Has(const std::map& labels) const { - auto hash = detail::hash_labels(labels); + const auto hash = detail::hash_labels(labels); std::lock_guard lock{mutex_}; return metrics_.find(hash) != metrics_.end(); } @@ -105,6 +105,7 @@ std::vector Family::Collect() const { family.name = name_; family.help = help_; family.type = T::metric_type; + family.metric.reserve(metrics_.size()); for (const auto& m : metrics_) { family.metric.push_back(std::move(CollectMetric(m.first, m.second.get()))); } @@ -114,7 +115,7 @@ std::vector Family::Collect() const { template ClientMetric Family::CollectMetric(std::size_t hash, T* metric) const { auto collected = metric->Collect(); - auto add_label = + const auto add_label = [&collected](const std::pair& label_pair) { auto label = ClientMetric::Label{}; label.name = label_pair.first; diff --git a/core/src/histogram.cc b/core/src/histogram.cc index 9c05d066..9906aa0b 100644 --- a/core/src/histogram.cc +++ b/core/src/histogram.cc @@ -47,6 +47,7 @@ ClientMetric Histogram::Collect() const { auto metric = ClientMetric{}; auto cumulative_count = 0ULL; + metric.histogram.bucket.reserve(bucket_counts_.size()); for (std::size_t i{0}; i < bucket_counts_.size(); ++i) { cumulative_count += bucket_counts_[i].Value(); auto bucket = ClientMetric::Bucket{}; diff --git a/core/src/summary.cc b/core/src/summary.cc index 5e309795..877c81bf 100644 --- a/core/src/summary.cc +++ b/core/src/summary.cc @@ -24,6 +24,7 @@ ClientMetric Summary::Collect() const { std::lock_guard lock(mutex_); + metric.summary.quantile.reserve(quantiles_.size()); for (const auto& quantile : quantiles_) { auto metricQuantile = ClientMetric::Quantile{}; metricQuantile.quantile = quantile.quantile; From baa6904f365581d967624afdcc6f67ddd10b015e Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Mon, 14 Jun 2021 09:03:50 +0200 Subject: [PATCH 172/206] chore: update googletest and curl --- 3rdparty/googletest | 2 +- bazel/civetweb.BUILD | 30 +++++++++--------------------- bazel/curl.BUILD | 12 ++++++++++-- bazel/curl.bzl | 3 +-- bazel/repositories.bzl | 14 +++++++------- 5 files changed, 28 insertions(+), 33 deletions(-) diff --git a/3rdparty/googletest b/3rdparty/googletest index 703bd9ca..e2239ee6 160000 --- a/3rdparty/googletest +++ b/3rdparty/googletest @@ -1 +1 @@ -Subproject commit 703bd9caab50b139428cea1aaff9974ebee5742e +Subproject commit e2239ee6043f73722e7aa812a459f54a28552929 diff --git a/bazel/civetweb.BUILD b/bazel/civetweb.BUILD index 6e5de4da..31b57aea 100644 --- a/bazel/civetweb.BUILD +++ b/bazel/civetweb.BUILD @@ -1,23 +1,17 @@ licenses(["notice"]) # MIT license config_setting( - name = "darwin", - values = {"cpu": "darwin"}, -) - -config_setting( - name = "darwin_x86_64", - values = {"cpu": "darwin_x86_64"}, + name = "osx", + constraint_values = [ + "@bazel_tools//platforms:osx", + ], ) config_setting( name = "windows", - values = {"cpu": "x64_windows"}, -) - -config_setting( - name = "windows_msvc", - values = {"cpu": "x64_windows_msvc"}, + constraint_values = [ + "@bazel_tools//platforms:windows", + ], ) cc_library( @@ -43,13 +37,10 @@ cc_library( ], linkopts = select({ ":windows": [], - ":windows_msvc": [], "//conditions:default": ["-lpthread"], }) + select({ - ":darwin": [], - ":darwin_x86_64": [], + ":osx": [], ":windows": [], - ":windows_msvc": [], "//conditions:default": ["-lrt"], }), textual_hdrs = [ @@ -80,13 +71,10 @@ cc_library( ], linkopts = select({ ":windows": [], - ":windows_msvc": [], "//conditions:default": ["-lpthread"], }) + select({ - ":darwin": [], - ":darwin_x86_64": [], + ":osx": [], ":windows": [], - ":windows_msvc": [], "//conditions:default": ["-lrt"], }), visibility = ["//visibility:public"], diff --git a/bazel/curl.BUILD b/bazel/curl.BUILD index 618462c1..eb045de2 100644 --- a/bazel/curl.BUILD +++ b/bazel/curl.BUILD @@ -22,13 +22,17 @@ package(features = ["no_copts_tokenization"]) config_setting( name = "windows", - values = {"cpu": "x64_windows"}, + constraint_values = [ + "@bazel_tools//platforms:windows", + ], visibility = ["//visibility:private"], ) config_setting( name = "osx", - values = {"cpu": "darwin"}, + constraint_values = [ + "@bazel_tools//platforms:osx", + ], visibility = ["//visibility:private"], ) @@ -56,6 +60,10 @@ cc_library( "-DEFAULTLIB:crypt32.lib", "-DEFAULTLIB:Normaliz.lib", ], + "//:osx": [ + "-framework SystemConfiguration", + "-lpthread", + ], "//conditions:default": [ "-lpthread", ], diff --git a/bazel/curl.bzl b/bazel/curl.bzl index 076f667b..796fe41e 100644 --- a/bazel/curl.bzl +++ b/bazel/curl.bzl @@ -55,7 +55,6 @@ BASE_CURL_COPTS = [ "-DHAVE_GETHOSTBYNAME_R_6=1", "-DHAVE_GETHOSTNAME=1", "-DHAVE_GETIFADDRS=1", - "-DHAVE_GETNAMEINFO=1", "-DHAVE_GETPPID=1", "-DHAVE_GETPWUID=1", "-DHAVE_GETPWUID_R=1", @@ -90,6 +89,7 @@ BASE_CURL_COPTS = [ "-DHAVE_PTHREAD_H=1", "-DHAVE_PWD_H=1", "-DHAVE_RECV=1", + "-DHAVE_SA_FAMILY_T=1", "-DHAVE_SELECT=1", "-DHAVE_SEND=1", "-DHAVE_SETJMP_H=1", @@ -150,7 +150,6 @@ BASE_CURL_COPTS = [ "-DRECV_TYPE_ARG3=size_t", "-DRECV_TYPE_ARG4=int", "-DRECV_TYPE_RETV=ssize_t", - "-DRETSIGTYPE=void", "-DSELECT_QUAL_ARG5=", "-DSELECT_TYPE_ARG1=int", "-DSELECT_TYPE_ARG234=fd_set*", diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index c2d75300..adaf2a0f 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -16,21 +16,21 @@ def prometheus_cpp_repositories(): maybe( http_archive, name = "com_google_googletest", - sha256 = "9dc9157a9a1551ec7a7e43daea9a694a0bb5fb8bec81235d8a1e6ef64c716dcb", - strip_prefix = "googletest-release-1.10.0", + sha256 = "b4870bf121ff7795ba20d20bcdd8627b8e088f2d1dab299a031c1034eddc93d5", + strip_prefix = "googletest-release-1.11.0", urls = [ - "https://github.com/google/googletest/archive/release-1.10.0.tar.gz", + "https://github.com/google/googletest/archive/release-1.11.0.tar.gz", ], ) maybe( http_archive, name = "com_github_curl", - sha256 = "5f85c4d891ccb14d6c3c701da3010c91c6570c3419391d485d95235253d837d7", - strip_prefix = "curl-7.76.1", + sha256 = "b0a3428acb60fa59044c4d0baae4e4fc09ae9af1d8a3aa84b2e3fbcd99841f77", + strip_prefix = "curl-7.77.0", urls = [ - "https://github.com/curl/curl/releases/download/curl-7_76_1/curl-7.76.1.tar.gz", - "https://curl.haxx.se/download/curl-7.76.1.tar.gz", + "https://github.com/curl/curl/releases/download/curl-7_77_0/curl-7.77.0.tar.gz", + "https://curl.haxx.se/download/curl-7.77.0.tar.gz", ], build_file = "@com_github_jupp0r_prometheus_cpp//bazel:curl.BUILD", ) From 8400b647f46a017222f9b9d5ca300ed20090d71f Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Mon, 14 Jun 2021 09:38:30 +0200 Subject: [PATCH 173/206] chore: add missing include for iwyu --- core/src/family.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/family.cc b/core/src/family.cc index eb2b1e3e..90314404 100644 --- a/core/src/family.cc +++ b/core/src/family.cc @@ -3,6 +3,7 @@ #include #include #include +#include #include #include "prometheus/check_names.h" From 7b616c0c5ac39d43ebf0cc49a2d9fc5b757932c2 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Wed, 21 Jul 2021 09:39:28 +0200 Subject: [PATCH 174/206] ci: select proper test configuration --- .github/workflows/cmake-ci.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cmake-ci.yml b/.github/workflows/cmake-ci.yml index 310c3ee1..562fae52 100644 --- a/.github/workflows/cmake-ci.yml +++ b/.github/workflows/cmake-ci.yml @@ -77,7 +77,11 @@ jobs: working-directory: "${{ github.workspace }}/_build" - name: "Test Release" - run: ctest -C Debug -V -LE Benchmark + run: ctest -C Release -V -LE Benchmark + working-directory: "${{ github.workspace }}/_build" + + - name: "Run Benchmark" + run: ctest -C Release -V -L Benchmark working-directory: "${{ github.workspace }}/_build" - name: "Install Debug" From aa17f5e81152e9a24cbb307bf010672b7d7a9bff Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Wed, 21 Jul 2021 09:29:42 +0200 Subject: [PATCH 175/206] chore: update curl and Google Benchmark --- bazel/repositories.bzl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index adaf2a0f..53c49016 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -26,11 +26,11 @@ def prometheus_cpp_repositories(): maybe( http_archive, name = "com_github_curl", - sha256 = "b0a3428acb60fa59044c4d0baae4e4fc09ae9af1d8a3aa84b2e3fbcd99841f77", - strip_prefix = "curl-7.77.0", + sha256 = "ed936c0b02c06d42cf84b39dd12bb14b62d77c7c4e875ade022280df5dcc81d7", + strip_prefix = "curl-7.78.0", urls = [ - "https://github.com/curl/curl/releases/download/curl-7_77_0/curl-7.77.0.tar.gz", - "https://curl.haxx.se/download/curl-7.77.0.tar.gz", + "https://github.com/curl/curl/releases/download/curl-7_78_0/curl-7.78.0.tar.gz", + "https://curl.haxx.se/download/curl-7.78.0.tar.gz", ], build_file = "@com_github_jupp0r_prometheus_cpp//bazel:curl.BUILD", ) @@ -38,10 +38,10 @@ def prometheus_cpp_repositories(): maybe( http_archive, name = "com_github_google_benchmark", - sha256 = "e4fbb85eec69e6668ad397ec71a3a3ab165903abe98a8327db920b94508f720e", - strip_prefix = "benchmark-1.5.3", + sha256 = "3bff5f237c317ddfd8d5a9b96b3eede7c0802e799db520d38ce756a2a46a18a0", + strip_prefix = "benchmark-1.5.5", urls = [ - "https://github.com/google/benchmark/archive/v1.5.3.tar.gz", + "https://github.com/google/benchmark/archive/v1.5.5.tar.gz", ], ) From 952c6bcdfec081f3259ebbaba8a03459ff57e1ba Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Wed, 21 Jul 2021 21:52:24 +0200 Subject: [PATCH 176/206] ci: Run iwyu 8.16 from Debian Experimental --- .github/workflows/linting.yml | 29 ++++++++++++++++------------- core/src/histogram.cc | 2 +- pull/src/handler.cc | 1 - 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 69181bc3..33e9aa52 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -4,8 +4,18 @@ on: [push, pull_request] jobs: iwyu: name: Include What You Use - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest + container: + image: debian:sid-slim steps: + - name: Install dependencies + run: | + echo "deb http://deb.debian.org/debian experimental main" > /etc/apt/sources.list.d/experimental.list + apt-get update + apt-get install -y --no-install-recommends ca-certificates clang-12 cmake git libbenchmark-dev libcurl4-openssl-dev ninja-build zlib1g-dev + apt-get install -y --no-install-recommends iwyu + apt-get -t experimental install -y iwyu # combine all three lines once iwyu 8.16 entered Debian Sid + - name: Checkout source uses: actions/checkout@v2 @@ -16,27 +26,20 @@ jobs: git submodule sync --recursive git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1 - - name: Install dependencies - run: | - sudo apt-get remove -y --purge man-db # avoid time-consuming trigger - sudo add-apt-repository ppa:gjasny/iwyu - sudo apt-get update - sudo apt-get install -y clang-11 iwyu libbenchmark-dev libcurl4-openssl-dev ninja-build zlib1g-dev - - name: "CMake Configure" - run: cmake -GNinja -DRUN_IWYU=ON -S ${{ github.workspace }} -B ${{ github.workspace }}/_build + run: cmake -GNinja -DRUN_IWYU=ON -DCMAKE_C_COMPILER=clang-12 -DCMAKE_CXX_COMPILER=clang++-12 -S ${GITHUB_WORKSPACE} -B ${GITHUB_WORKSPACE}/_build - name: Build - run: cmake --build ${{ github.workspace }}/_build 2>&1 | tee ${{ github.workspace }}/output.txt + run: cmake --build ${GITHUB_WORKSPACE}/_build 2>&1 | tee ${GITHUB_WORKSPACE}/output.txt - name: Check build output - run: if egrep -q 'should (add|remove) these lines' ${{ github.workspace }}/output.txt; then exit 1; fi + run: if egrep -q 'should (add|remove) these lines' ${GITHUB_WORKSPACE}/output.txt; then exit 1; fi #- name: "CMake Configure" - # run: cmake -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -S ${{ github.workspace }} -B ${{ github.workspace }}/_build + # run: cmake -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -S ${GITHUB_WORKSPACE} -B ${GITHUB_WORKSPACE}/_build #- name: "Run IWYU" - # run: iwyu_tool -p ${{ github.workspace }}/_build core push pull -- -Xiwyu --mapping_file=${{ github.workspace }}/cmake/googletest.imp -Xiwyu --no_fwd_decls 2>&1 | tee ${{ github.workspace }}/output.txt + # run: iwyu_tool -p ${GITHUB_WORKSPACE}/_build core push pull -- -Xiwyu --mapping_file=${GITHUB_WORKSPACE}/cmake/googletest.imp -Xiwyu --no_fwd_decls 2>&1 | tee ${{ github.workspace }}/output.txt format: name: Clang Format diff --git a/core/src/histogram.cc b/core/src/histogram.cc index 9906aa0b..78ba3c88 100644 --- a/core/src/histogram.cc +++ b/core/src/histogram.cc @@ -2,10 +2,10 @@ #include #include +#include #include #include #include -#include #include #include diff --git a/pull/src/handler.cc b/pull/src/handler.cc index da8f7055..5a55001b 100644 --- a/pull/src/handler.cc +++ b/pull/src/handler.cc @@ -2,7 +2,6 @@ #include #include -#include #include #include #include From 9e264c41ee9dd68f8d35fe2455533bc97daa92bc Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 2 Sep 2021 12:26:13 +0200 Subject: [PATCH 177/206] feat(pull): Use civetweb 1.15 --- bazel/repositories.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index 53c49016..16180aed 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -5,10 +5,10 @@ def prometheus_cpp_repositories(): maybe( http_archive, name = "civetweb", - strip_prefix = "civetweb-1.14", - sha256 = "d02d7ab091c8b4edf21fc13a03c6db08a8a8b8605e35e0073251b9d88443c653", + strip_prefix = "civetweb-1.15", + sha256 = "90a533422944ab327a4fbb9969f0845d0dba05354f9cacce3a5005fa59f593b9", urls = [ - "https://github.com/civetweb/civetweb/archive/v1.14.tar.gz", + "https://github.com/civetweb/civetweb/archive/v1.15.tar.gz", ], build_file = "@com_github_jupp0r_prometheus_cpp//bazel:civetweb.BUILD", ) From 8b67e5f1770224f08975fa8d99838e05a4f15635 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 9 Sep 2021 15:05:02 +0200 Subject: [PATCH 178/206] docs: update Readme Fixes: #511 --- README.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 68e48918..bfe7e092 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,7 @@ int main() { ## Requirements -Using `prometheus-cpp` requires a C++11 compliant compiler. It has been successfully tested with GNU GCC 4.8 on Ubuntu Trusty and Visual Studio 2017 (but Visual Studio 2015 should work, too). +Using `prometheus-cpp` requires a C++11 compliant compiler. It has been successfully tested with GNU GCC 7.4 on Ubuntu Bionic (18.04) and Visual Studio 2017 (but Visual Studio 2015 should work, too). ## Building @@ -102,11 +102,15 @@ and [bazel](https://bazel.io). Both are tested in CI and should work on master and for all releases. In case these instructions don't work for you, looking at -the [travis build script](.travis.yml) might help. +the [GitHub Workflows](.github/workflows) might help. ### via CMake -For CMake builds don't forget to fetch the submodules first. Then build as usual. +For CMake builds don't forget to fetch the submodules first. Please note that +[zlib](https://zlib.net/) and [libcurl](https://curl.se/) are not provided by +the included submodules. In the example below their usage is disabled. + +Then build as usual. ``` shell # fetch third-party dependencies @@ -117,17 +121,16 @@ mkdir _build cd _build # run cmake -cmake .. -DBUILD_SHARED_LIBS=ON # or OFF for static libraries +cmake .. -DBUILD_SHARED_LIBS=ON -DENABLE_PUSH=OFF -DENABLE_COMPRESSION=OFF # build -make -j 4 +cmake --build . --parallel 4 # run tests ctest -V # install the libraries and headers -mkdir -p deploy -make DESTDIR=`pwd`/deploy install +cmake --install . ``` ### via Bazel From 70a930fb1548250882f9a216249e2dc95c10cf98 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 9 Sep 2021 14:44:43 +0200 Subject: [PATCH 179/206] chore: Use Google Benchmark 1.6.0 --- bazel/repositories.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index 16180aed..23e9556a 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -38,10 +38,10 @@ def prometheus_cpp_repositories(): maybe( http_archive, name = "com_github_google_benchmark", - sha256 = "3bff5f237c317ddfd8d5a9b96b3eede7c0802e799db520d38ce756a2a46a18a0", - strip_prefix = "benchmark-1.5.5", + sha256 = "1f71c72ce08d2c1310011ea6436b31e39ccab8c2db94186d26657d41747c85d6", + strip_prefix = "benchmark-1.6.0", urls = [ - "https://github.com/google/benchmark/archive/v1.5.5.tar.gz", + "https://github.com/google/benchmark/archive/v1.6.0.tar.gz", ], ) From f9597c7c2217a1f06a3c65c0c00372ba814605ba Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 9 Sep 2021 14:34:56 +0200 Subject: [PATCH 180/206] chore(pull): Use civetweb 1.15 --- 3rdparty/civetweb | 2 +- cmake/civetweb-3rdparty-config.cmake | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/3rdparty/civetweb b/3rdparty/civetweb index c1d08d3c..eefb26f8 160000 --- a/3rdparty/civetweb +++ b/3rdparty/civetweb @@ -1 +1 @@ -Subproject commit c1d08d3c35bc939da7bec09973bda77c702c1d00 +Subproject commit eefb26f82b233268fc98577d265352720d477ba4 diff --git a/cmake/civetweb-3rdparty-config.cmake b/cmake/civetweb-3rdparty-config.cmake index 642226e3..8cc73cf9 100644 --- a/cmake/civetweb-3rdparty-config.cmake +++ b/cmake/civetweb-3rdparty-config.cmake @@ -32,6 +32,7 @@ target_compile_definitions(civetweb NO_CGI NO_CACHING NO_FILES + SOCKET_TIMEOUT_QUANTUM=200 ) target_compile_options(civetweb From 03f30b6f2fcad9aa0dc529d11f8fd79643e20d49 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 9 Sep 2021 17:45:07 +0200 Subject: [PATCH 181/206] ci: iwyu entered Debian Sid --- .github/workflows/linting.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 33e9aa52..99d82503 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -10,11 +10,8 @@ jobs: steps: - name: Install dependencies run: | - echo "deb http://deb.debian.org/debian experimental main" > /etc/apt/sources.list.d/experimental.list apt-get update - apt-get install -y --no-install-recommends ca-certificates clang-12 cmake git libbenchmark-dev libcurl4-openssl-dev ninja-build zlib1g-dev - apt-get install -y --no-install-recommends iwyu - apt-get -t experimental install -y iwyu # combine all three lines once iwyu 8.16 entered Debian Sid + apt-get install -y --no-install-recommends ca-certificates clang-12 cmake git iwyu libbenchmark-dev libcurl4-openssl-dev ninja-build zlib1g-dev - name: Checkout source uses: actions/checkout@v2 From 95ea1a3169c88da612f7d9918b9fd67a201fe994 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 9 Sep 2021 17:25:57 +0200 Subject: [PATCH 182/206] chore: prepare 0.13.0 release --- CMakeLists.txt | 2 +- pull/include/prometheus/exposer.h | 14 +++----------- pull/src/exposer.cc | 6 ------ 3 files changed, 4 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d803bac..e7836adb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ if(POLICY CMP0091) endif() project(prometheus-cpp - VERSION 0.12.3 + VERSION 0.13.0 DESCRIPTION "Prometheus Client Library for Modern C++" HOMEPAGE_URL "https://github.com/jupp0r/prometheus-cpp" ) diff --git a/pull/include/prometheus/exposer.h b/pull/include/prometheus/exposer.h index 85804f04..793225a5 100644 --- a/pull/include/prometheus/exposer.h +++ b/pull/include/prometheus/exposer.h @@ -20,19 +20,11 @@ class Endpoint; class PROMETHEUS_CPP_PULL_EXPORT Exposer { public: - /// @note This ctor will be merged with the "callback" variant once - /// prometheus-cpp 0.13 performs an ABI-break explicit Exposer(const std::string& bind_address, - const std::size_t num_threads = 2); - /// @note This ctor will be merged with the "callback" variant once - /// prometheus-cpp 0.13 performs an ABI-break - explicit Exposer(std::vector options); - - explicit Exposer(const std::string& bind_address, - const std::size_t num_threads, - const CivetCallbacks* callbacks); + const std::size_t num_threads = 2, + const CivetCallbacks* callbacks = nullptr); explicit Exposer(std::vector options, - const CivetCallbacks* callbacks); + const CivetCallbacks* callbacks = nullptr); ~Exposer(); void RegisterCollectable(const std::weak_ptr& collectable, const std::string& uri = std::string("/metrics")); diff --git a/pull/src/exposer.cc b/pull/src/exposer.cc index f278bbb9..546c9bc1 100644 --- a/pull/src/exposer.cc +++ b/pull/src/exposer.cc @@ -11,12 +11,6 @@ namespace prometheus { -Exposer::Exposer(const std::string& bind_address, const std::size_t num_threads) - : Exposer(bind_address, num_threads, nullptr) {} - -Exposer::Exposer(std::vector options) - : Exposer(options, nullptr) {} - Exposer::Exposer(const std::string& bind_address, const std::size_t num_threads, const CivetCallbacks* callbacks) : Exposer( From 342de5e93bd0cbafde77ec801f9dd35a03bceb3f Mon Sep 17 00:00:00 2001 From: Ashish Yadav <57518243+ashishyadav250@users.noreply.github.com> Date: Thu, 9 Sep 2021 17:05:51 +0200 Subject: [PATCH 183/206] fix(core): Locale-independent floating-point serialization Fixes: #509 --- core/src/text_serializer.cc | 41 ++++++++----------------------------- 1 file changed, 9 insertions(+), 32 deletions(-) diff --git a/core/src/text_serializer.cc b/core/src/text_serializer.cc index 71af4ab9..d26d3e58 100644 --- a/core/src/text_serializer.cc +++ b/core/src/text_serializer.cc @@ -1,21 +1,11 @@ #include "prometheus/text_serializer.h" -#include #include +#include #include #include -#include #include -#if __cpp_lib_to_chars >= 201611L -#include -#include -#include -#else -#include -#include -#endif - #include "prometheus/client_metric.h" #include "prometheus/metric_family.h" #include "prometheus/metric_type.h" @@ -31,26 +21,7 @@ void WriteValue(std::ostream& out, double value) { } else if (std::isinf(value)) { out << (value < 0 ? "-Inf" : "+Inf"); } else { - std::array buffer; - -#if __cpp_lib_to_chars >= 201611L - auto [ptr, ec] = - std::to_chars(buffer.data(), buffer.data() + buffer.size(), value); - if (ec != std::errc()) { - throw std::runtime_error("Could not convert double to string: " + - std::make_error_code(ec).message()); - } - out.write(buffer.data(), ptr - buffer.data()); -#else - auto wouldHaveWritten = - std::snprintf(buffer.data(), buffer.size(), "%.*g", - std::numeric_limits::max_digits10 - 1, value); - if (wouldHaveWritten <= 0 || - static_cast(wouldHaveWritten) >= buffer.size()) { - throw std::runtime_error("Could not convert double to string"); - } - out.write(buffer.data(), wouldHaveWritten); -#endif + out << value; } } @@ -217,11 +188,17 @@ void SerializeFamily(std::ostream& out, const MetricFamily& family) { void TextSerializer::Serialize(std::ostream& out, const std::vector& metrics) const { - std::locale saved_locale = out.getloc(); + auto saved_locale = out.getloc(); + auto saved_precision = out.precision(); + out.imbue(std::locale::classic()); + out.precision(std::numeric_limits::max_digits10 - 1); + for (auto& family : metrics) { SerializeFamily(out, family); } + out.imbue(saved_locale); + out.precision(saved_precision); } } // namespace prometheus From 1a66113c2dda871288dd2b1da3d0e34b03f3c250 Mon Sep 17 00:00:00 2001 From: Jinesi Yelizati Date: Tue, 21 Sep 2021 16:53:14 +0800 Subject: [PATCH 184/206] fix(readme): update the link to the cmake example --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bfe7e092..fcf4a3bc 100644 --- a/README.md +++ b/README.md @@ -210,7 +210,7 @@ Consuming prometheus-cpp via CMake is the preferred way because all the dependen between the three prometheus-cpp libraries are handled correctly. The `cmake/project-import` directory contains an -example project and minimal [CMakeLists.txt](cmake/project-import/CMakeLists.txt). +example project and minimal [CMakeLists.txt](cmake/project-import-cmake/CMakeLists.txt). ### vcpkg From 722fbcf18695976b23f81d1e852b8fdb4690cfd9 Mon Sep 17 00:00:00 2001 From: Tim Wynants Date: Thu, 14 Oct 2021 15:33:54 +0200 Subject: [PATCH 185/206] fix: there is a race condition when pushing and collecting histogram data All increment counters and the total could be changed by an other threads is preparing the cumulative data collection. --- core/include/prometheus/histogram.h | 2 ++ core/src/histogram.cc | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/core/include/prometheus/histogram.h b/core/include/prometheus/histogram.h index f8be2435..a26f8432 100644 --- a/core/include/prometheus/histogram.h +++ b/core/include/prometheus/histogram.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include "prometheus/client_metric.h" @@ -68,6 +69,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Histogram { private: const BucketBoundaries bucket_boundaries_; + mutable std::mutex mutex_; std::vector bucket_counts_; Gauge sum_; }; diff --git a/core/src/histogram.cc b/core/src/histogram.cc index 78ba3c88..4947b3a7 100644 --- a/core/src/histogram.cc +++ b/core/src/histogram.cc @@ -24,6 +24,8 @@ void Histogram::Observe(const double value) { std::find_if( std::begin(bucket_boundaries_), std::end(bucket_boundaries_), [value](const double boundary) { return boundary >= value; }))); + + std::lock_guard lock(mutex_); sum_.Increment(value); bucket_counts_[bucket_index].Increment(); } @@ -36,6 +38,7 @@ void Histogram::ObserveMultiple(const std::vector& bucket_increments, "the number of buckets in the histogram."); } + std::lock_guard lock(mutex_); sum_.Increment(sum_of_values); for (std::size_t i{0}; i < bucket_counts_.size(); ++i) { @@ -44,6 +47,8 @@ void Histogram::ObserveMultiple(const std::vector& bucket_increments, } ClientMetric Histogram::Collect() const { + std::lock_guard lock(mutex_); + auto metric = ClientMetric{}; auto cumulative_count = 0ULL; From ddf7083db2125c58e098a4d1d52bccf9ae4bc2ac Mon Sep 17 00:00:00 2001 From: Stephane Janel Date: Sun, 7 Nov 2021 12:03:47 +0100 Subject: [PATCH 186/206] Rule of Five applied on Gateway, avoid unnecessary copies of std::string --- push/include/prometheus/gateway.h | 12 +++++++++--- push/src/gateway.cc | 13 ++++++++++--- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/push/include/prometheus/gateway.h b/push/include/prometheus/gateway.h index 8e0191e3..d8270805 100644 --- a/push/include/prometheus/gateway.h +++ b/push/include/prometheus/gateway.h @@ -19,9 +19,15 @@ class PROMETHEUS_CPP_PUSH_EXPORT Gateway { public: using Labels = std::map; - Gateway(const std::string host, const std::string port, - const std::string jobname, const Labels& labels = {}, - const std::string username = {}, const std::string password = {}); + Gateway(const std::string& host, const std::string& port, + const std::string& jobname, const Labels& labels = {}, + const std::string& username = {}, const std::string& password = {}); + + Gateway(const Gateway&) = delete; + Gateway(Gateway&&) = delete; + Gateway& operator=(const Gateway&) = delete; + Gateway& operator=(Gateway&&) = delete; + ~Gateway(); void RegisterCollectable(const std::weak_ptr& collectable, diff --git a/push/src/gateway.cc b/push/src/gateway.cc index 2f644eac..48ec3016 100644 --- a/push/src/gateway.cc +++ b/push/src/gateway.cc @@ -23,6 +23,13 @@ static const char CONTENT_TYPE[] = class CurlWrapper { public: + CurlWrapper() noexcept = default; + + CurlWrapper(const CurlWrapper&) = delete; + CurlWrapper(CurlWrapper&&) = delete; + CurlWrapper& operator=(const CurlWrapper&) = delete; + CurlWrapper& operator=(CurlWrapper&&) = delete; + ~CurlWrapper() { curl_easy_cleanup(curl_); } CURL* curl() { @@ -36,9 +43,9 @@ class CurlWrapper { CURL* curl_ = nullptr; }; -Gateway::Gateway(const std::string host, const std::string port, - const std::string jobname, const Labels& labels, - const std::string username, const std::string password) { +Gateway::Gateway(const std::string& host, const std::string& port, + const std::string& jobname, const Labels& labels, + const std::string& username, const std::string& password) { /* In windows, this will init the winsock stuff */ curl_global_init(CURL_GLOBAL_ALL); curlWrapper_ = detail::make_unique(); From 755f8424d3d5931d1b1714e280b03bd6a2731e2d Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 11 Nov 2021 20:59:14 +0100 Subject: [PATCH 187/206] fix(clang-tidy): Fix errors detected by clang-tidy --- core/benchmarks/histogram_bench.cc | 6 ++++-- core/tests/summary_test.cc | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/core/benchmarks/histogram_bench.cc b/core/benchmarks/histogram_bench.cc index 64729451..9c447474 100644 --- a/core/benchmarks/histogram_bench.cc +++ b/core/benchmarks/histogram_bench.cc @@ -1,6 +1,7 @@ #include #include +#include #include #include #include @@ -11,8 +12,9 @@ using prometheus::Histogram; -static Histogram::BucketBoundaries CreateLinearBuckets(double start, double end, - double step) { +static Histogram::BucketBoundaries CreateLinearBuckets(std::int64_t start, + std::int64_t end, + std::int64_t step) { auto bucket_boundaries = Histogram::BucketBoundaries{}; for (auto i = start; i < end; i += step) { bucket_boundaries.push_back(i); diff --git a/core/tests/summary_test.cc b/core/tests/summary_test.cc index 4b28bc26..32b1e804 100644 --- a/core/tests/summary_test.cc +++ b/core/tests/summary_test.cc @@ -75,7 +75,7 @@ TEST(SummaryTest, max_age) { 2}; summary.Observe(8.0); - static const auto test_value = [&summary](double ref) { + const auto test_value = [&summary](double ref) { auto metric = summary.Collect(); auto s = metric.summary; ASSERT_EQ(s.quantile.size(), 1U); From f35499ba5bf2a754f40ee021db0c13428a19c77d Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 11 Nov 2021 21:13:08 +0100 Subject: [PATCH 188/206] chore(clang-tidy): Fix modernize-use-override --- core/include/prometheus/registry.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/include/prometheus/registry.h b/core/include/prometheus/registry.h index ef83438c..8a5b78e1 100644 --- a/core/include/prometheus/registry.h +++ b/core/include/prometheus/registry.h @@ -62,7 +62,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Registry : public Collectable { explicit Registry(InsertBehavior insert_behavior = InsertBehavior::Merge); /// \brief name Destroys a registry. - ~Registry(); + ~Registry() override; /// \brief Returns a list of metrics and their samples. /// From a3e4d4289d48722675570e53255f2fe9dde52421 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 11 Nov 2021 21:34:28 +0100 Subject: [PATCH 189/206] chore(clang-tidy): Fix cppcoreguidelines-special-member-functions --- core/include/prometheus/registry.h | 12 ++++++++++++ core/tests/raii_locale.h | 5 +++++ pull/include/prometheus/exposer.h | 6 ++++++ pull/src/endpoint.h | 5 +++++ 4 files changed, 28 insertions(+) diff --git a/core/include/prometheus/registry.h b/core/include/prometheus/registry.h index 8a5b78e1..2ca183f2 100644 --- a/core/include/prometheus/registry.h +++ b/core/include/prometheus/registry.h @@ -61,6 +61,18 @@ class PROMETHEUS_CPP_CORE_EXPORT Registry : public Collectable { /// \param insert_behavior How to handle families with the same name. explicit Registry(InsertBehavior insert_behavior = InsertBehavior::Merge); + /// \brief Deleted copy constructor. + Registry(const Registry&) = delete; + + /// \brief Deleted copy assignment. + Registry& operator=(const Registry&) = delete; + + /// \brief Deleted move constructor. + Registry(Registry&&) = delete; + + /// \brief Deleted move assignment. + Registry& operator=(Registry&&) = delete; + /// \brief name Destroys a registry. ~Registry() override; diff --git a/core/tests/raii_locale.h b/core/tests/raii_locale.h index 592d74f2..481cd846 100644 --- a/core/tests/raii_locale.h +++ b/core/tests/raii_locale.h @@ -10,6 +10,11 @@ class RAIILocale { ~RAIILocale() { std::locale::global(savedLocale_); } + RAIILocale(const RAIILocale&) = delete; + RAIILocale(RAIILocale&&) = delete; + RAIILocale& operator=(const RAIILocale&) = delete; + RAIILocale& operator=(RAIILocale&&) = delete; + private: const std::locale savedLocale_; }; diff --git a/pull/include/prometheus/exposer.h b/pull/include/prometheus/exposer.h index 793225a5..b470fbd0 100644 --- a/pull/include/prometheus/exposer.h +++ b/pull/include/prometheus/exposer.h @@ -26,6 +26,12 @@ class PROMETHEUS_CPP_PULL_EXPORT Exposer { explicit Exposer(std::vector options, const CivetCallbacks* callbacks = nullptr); ~Exposer(); + + Exposer(const Exposer&) = delete; + Exposer(Exposer&&) = delete; + Exposer& operator=(const Exposer&) = delete; + Exposer& operator=(Exposer&&) = delete; + void RegisterCollectable(const std::weak_ptr& collectable, const std::string& uri = std::string("/metrics")); diff --git a/pull/src/endpoint.h b/pull/src/endpoint.h index e0605e35..81bb48f9 100644 --- a/pull/src/endpoint.h +++ b/pull/src/endpoint.h @@ -18,6 +18,11 @@ class Endpoint { explicit Endpoint(CivetServer& server, std::string uri); ~Endpoint(); + Endpoint(const Endpoint&) = delete; + Endpoint(Endpoint&&) = delete; + Endpoint& operator=(const Endpoint&) = delete; + Endpoint& operator=(Endpoint&&) = delete; + void RegisterCollectable(const std::weak_ptr& collectable); void RegisterAuth( std::function authCB, From 1d4e4649c30350dcf0744bc82a838f9a6ff9a638 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Fri, 12 Nov 2021 08:29:43 +0100 Subject: [PATCH 190/206] docs(core): Document atomic increment Issue: #293 Issue: #526 Issue: #531 --- core/src/gauge.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/src/gauge.cc b/core/src/gauge.cc index b3933076..251fba27 100644 --- a/core/src/gauge.cc +++ b/core/src/gauge.cc @@ -17,9 +17,11 @@ void Gauge::Decrement(const double value) { Change(-1.0 * value); } void Gauge::Set(const double value) { value_.store(value); } void Gauge::Change(const double value) { + // C++ 20 will add std::atomic::fetch_add support for floating point types auto current = value_.load(); - while (!value_.compare_exchange_weak(current, current + value)) - ; + while (!value_.compare_exchange_weak(current, current + value)) { + // intentionally empty block + } } void Gauge::SetToCurrentTime() { From e5598fb249d4d0544ecf2cdc18f2d110d3357481 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Fri, 12 Nov 2021 08:53:27 +0100 Subject: [PATCH 191/206] chore(push): Use curl 7.80.0 --- bazel/repositories.bzl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index 23e9556a..9c0e87fe 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -26,11 +26,11 @@ def prometheus_cpp_repositories(): maybe( http_archive, name = "com_github_curl", - sha256 = "ed936c0b02c06d42cf84b39dd12bb14b62d77c7c4e875ade022280df5dcc81d7", - strip_prefix = "curl-7.78.0", + sha256 = "dab997c9b08cb4a636a03f2f7f985eaba33279c1c52692430018fae4a4878dc7", + strip_prefix = "curl-7.80.0", urls = [ - "https://github.com/curl/curl/releases/download/curl-7_78_0/curl-7.78.0.tar.gz", - "https://curl.haxx.se/download/curl-7.78.0.tar.gz", + "https://github.com/curl/curl/releases/download/curl-7_80_0/curl-7.80.0.tar.gz", + "https://curl.haxx.se/download/curl-7.80.0.tar.gz", ], build_file = "@com_github_jupp0r_prometheus_cpp//bazel:curl.BUILD", ) From 556d4ed645230c85c2c51da492d8d3765b9a1c54 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Fri, 12 Nov 2021 08:57:32 +0100 Subject: [PATCH 192/206] docs: Prepare for 1.0.0 release Issue: #525 --- CMakeLists.txt | 2 +- README.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e7836adb..4ee6812c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ if(POLICY CMP0091) endif() project(prometheus-cpp - VERSION 0.13.0 + VERSION 1.0.0 DESCRIPTION "Prometheus Client Library for Modern C++" HOMEPAGE_URL "https://github.com/jupp0r/prometheus-cpp" ) diff --git a/README.md b/README.md index fcf4a3bc..3647861b 100644 --- a/README.md +++ b/README.md @@ -361,9 +361,9 @@ BM_Summary_Collect_Common/262144 128723 ns 126987 ns 55 ``` ## Project Status -Beta, getting ready for 1.0. The library is pretty stable and used in -production. There are some small breaking API changes that might -happen before 1.0 Parts of the library are instrumented by itself +Stable and used in production. + +Parts of the library are instrumented by itself (bytes scraped, number of scrapes, scrape request latencies). There is a working [example](pull/tests/integration/sample_server.cc) that's scraped by telegraf as part of integration tests. From b6615c7a626a0f51b8eca28f2610c4f8903f4a36 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Fri, 12 Nov 2021 09:11:03 +0100 Subject: [PATCH 193/206] fix(pull): Properly lock Exposer functions Fixes: #529 --- pull/include/prometheus/exposer.h | 2 ++ pull/src/exposer.cc | 3 +++ 2 files changed, 5 insertions(+) diff --git a/pull/include/prometheus/exposer.h b/pull/include/prometheus/exposer.h index b470fbd0..83e0e7f0 100644 --- a/pull/include/prometheus/exposer.h +++ b/pull/include/prometheus/exposer.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -50,6 +51,7 @@ class PROMETHEUS_CPP_PULL_EXPORT Exposer { std::unique_ptr server_; std::vector> endpoints_; + std::mutex mutex_; }; } // namespace prometheus diff --git a/pull/src/exposer.cc b/pull/src/exposer.cc index 546c9bc1..5ee3adea 100644 --- a/pull/src/exposer.cc +++ b/pull/src/exposer.cc @@ -27,6 +27,7 @@ Exposer::~Exposer() = default; void Exposer::RegisterCollectable(const std::weak_ptr& collectable, const std::string& uri) { + std::lock_guard lock{mutex_}; auto& endpoint = GetEndpointForUri(uri); endpoint.RegisterCollectable(collectable); } @@ -34,12 +35,14 @@ void Exposer::RegisterCollectable(const std::weak_ptr& collectable, void Exposer::RegisterAuth( std::function authCB, const std::string& realm, const std::string& uri) { + std::lock_guard lock{mutex_}; auto& endpoint = GetEndpointForUri(uri); endpoint.RegisterAuth(std::move(authCB), realm); } void Exposer::RemoveCollectable(const std::weak_ptr& collectable, const std::string& uri) { + std::lock_guard lock{mutex_}; auto& endpoint = GetEndpointForUri(uri); endpoint.RemoveCollectable(collectable); } From 882fec94bf36be409ce1865f02fcd25ad418c357 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Fri, 12 Nov 2021 09:52:27 +0100 Subject: [PATCH 194/206] chore(push): Refactored curl_wrapper --- push/CMakeLists.txt | 2 + push/include/prometheus/detail/http_method.h | 12 ++ push/include/prometheus/gateway.h | 21 +--- push/src/curl_wrapper.cc | 88 ++++++++++++++ push/src/curl_wrapper.h | 32 ++++++ push/src/gateway.cc | 115 +++---------------- 6 files changed, 157 insertions(+), 113 deletions(-) create mode 100644 push/include/prometheus/detail/http_method.h create mode 100644 push/src/curl_wrapper.cc create mode 100644 push/src/curl_wrapper.h diff --git a/push/CMakeLists.txt b/push/CMakeLists.txt index d8690c38..191504a8 100644 --- a/push/CMakeLists.txt +++ b/push/CMakeLists.txt @@ -2,6 +2,8 @@ find_package(CURL REQUIRED) add_library(push + src/curl_wrapper.cc + src/curl_wrapper.h src/gateway.cc ) diff --git a/push/include/prometheus/detail/http_method.h b/push/include/prometheus/detail/http_method.h new file mode 100644 index 00000000..21eb1820 --- /dev/null +++ b/push/include/prometheus/detail/http_method.h @@ -0,0 +1,12 @@ +#pragma once + +namespace prometheus { +namespace detail { +enum class HttpMethod { + Post, + Put, + Delete, +}; + +} // namespace detail +} // namespace prometheus diff --git a/push/include/prometheus/gateway.h b/push/include/prometheus/gateway.h index d8270805..665a858b 100644 --- a/push/include/prometheus/gateway.h +++ b/push/include/prometheus/gateway.h @@ -3,17 +3,19 @@ #include #include #include -#include #include #include #include #include "prometheus/collectable.h" +#include "prometheus/detail/http_method.h" #include "prometheus/detail/push_export.h" namespace prometheus { +namespace detail { class CurlWrapper; +} class PROMETHEUS_CPP_PUSH_EXPORT Gateway { public: @@ -54,27 +56,16 @@ class PROMETHEUS_CPP_PUSH_EXPORT Gateway { private: std::string jobUri_; std::string labels_; - std::string auth_; - std::unique_ptr curlWrapper_; - std::mutex mutex_; + std::unique_ptr curlWrapper_; using CollectableEntry = std::pair, std::string>; std::vector collectables_; std::string getUri(const CollectableEntry& collectable) const; - enum class HttpMethod { - Post, - Put, - Delete, - }; + int push(detail::HttpMethod method); - int performHttpRequest(HttpMethod method, const std::string& uri, - const std::string& body); - - int push(HttpMethod method); - - std::future async_push(HttpMethod method); + std::future async_push(detail::HttpMethod method); static void CleanupStalePointers(std::vector& collectables); }; diff --git a/push/src/curl_wrapper.cc b/push/src/curl_wrapper.cc new file mode 100644 index 00000000..37e58564 --- /dev/null +++ b/push/src/curl_wrapper.cc @@ -0,0 +1,88 @@ +#include "curl_wrapper.h" + +#include + +namespace prometheus { +namespace detail { + +static const char CONTENT_TYPE[] = + "Content-Type: text/plain; version=0.0.4; charset=utf-8"; + +CurlWrapper::CurlWrapper(const std::string& username, + const std::string& password) { + /* In windows, this will init the winsock stuff */ + auto error = curl_global_init(CURL_GLOBAL_ALL); + if (error) { + throw std::runtime_error("Cannot initialize global curl!"); + } + + curl_ = curl_easy_init(); + if (!curl_) { + curl_global_cleanup(); + throw std::runtime_error("Cannot initialize easy curl!"); + } + + if (!username.empty()) { + auth_ = username + ":" + password; + } +} + +CurlWrapper::~CurlWrapper() { + curl_easy_cleanup(curl_); + curl_global_cleanup(); +} + +int CurlWrapper::performHttpRequest(HttpMethod method, const std::string& uri, + const std::string& body) { + std::lock_guard l(mutex_); + + curl_easy_reset(curl_); + curl_easy_setopt(curl_, CURLOPT_URL, uri.c_str()); + + curl_slist* header_chunk = nullptr; + header_chunk = curl_slist_append(header_chunk, CONTENT_TYPE); + curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, header_chunk); + + if (!body.empty()) { + curl_easy_setopt(curl_, CURLOPT_POSTFIELDSIZE, body.size()); + curl_easy_setopt(curl_, CURLOPT_POSTFIELDS, body.data()); + } + + if (!auth_.empty()) { + curl_easy_setopt(curl_, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + curl_easy_setopt(curl_, CURLOPT_USERPWD, auth_.c_str()); + } + + switch (method) { + case HttpMethod::Post: + curl_easy_setopt(curl_, CURLOPT_POST, 1L); + break; + + case HttpMethod::Put: + curl_easy_setopt(curl_, CURLOPT_NOBODY, 0L); + curl_easy_setopt(curl_, CURLOPT_CUSTOMREQUEST, "PUT"); + break; + + case HttpMethod::Delete: + curl_easy_setopt(curl_, CURLOPT_HTTPGET, 0L); + curl_easy_setopt(curl_, CURLOPT_NOBODY, 0L); + curl_easy_setopt(curl_, CURLOPT_CUSTOMREQUEST, "DELETE"); + break; + } + + auto curl_error = curl_easy_perform(curl_); + + long response_code; + curl_easy_getinfo(curl_, CURLINFO_RESPONSE_CODE, &response_code); + + curl_slist_free_all(header_chunk); + + if (curl_error != CURLE_OK) { + return -curl_error; + } + + return response_code; +} + +} // namespace detail +} // namespace prometheus diff --git a/push/src/curl_wrapper.h b/push/src/curl_wrapper.h new file mode 100644 index 00000000..df20d6bb --- /dev/null +++ b/push/src/curl_wrapper.h @@ -0,0 +1,32 @@ +#include + +#include +#include + +#include "prometheus/detail/http_method.h" + +namespace prometheus { +namespace detail { + +class CurlWrapper { + public: + CurlWrapper(const std::string& username, const std::string& password); + + CurlWrapper(const CurlWrapper&) = delete; + CurlWrapper(CurlWrapper&&) = delete; + CurlWrapper& operator=(const CurlWrapper&) = delete; + CurlWrapper& operator=(CurlWrapper&&) = delete; + + ~CurlWrapper(); + + int performHttpRequest(HttpMethod method, const std::string& uri, + const std::string& body); + + private: + CURL* curl_; + std::string auth_; + std::mutex mutex_; +}; + +} // namespace detail +} // namespace prometheus diff --git a/push/src/gateway.cc b/push/src/gateway.cc index 48ec3016..f1b8ef73 100644 --- a/push/src/gateway.cc +++ b/push/src/gateway.cc @@ -1,14 +1,13 @@ #include "prometheus/gateway.h" -#include - #include #include #include #include #include +#include "curl_wrapper.h" #include "prometheus/detail/future_std.h" #include "prometheus/metric_family.h" // IWYU pragma: keep #include "prometheus/text_serializer.h" @@ -21,43 +20,15 @@ namespace prometheus { static const char CONTENT_TYPE[] = "Content-Type: text/plain; version=0.0.4; charset=utf-8"; -class CurlWrapper { - public: - CurlWrapper() noexcept = default; - - CurlWrapper(const CurlWrapper&) = delete; - CurlWrapper(CurlWrapper&&) = delete; - CurlWrapper& operator=(const CurlWrapper&) = delete; - CurlWrapper& operator=(CurlWrapper&&) = delete; - - ~CurlWrapper() { curl_easy_cleanup(curl_); } - - CURL* curl() { - if (!curl_) { - curl_ = curl_easy_init(); - } - return curl_; - } - - private: - CURL* curl_ = nullptr; -}; - Gateway::Gateway(const std::string& host, const std::string& port, const std::string& jobname, const Labels& labels, const std::string& username, const std::string& password) { - /* In windows, this will init the winsock stuff */ - curl_global_init(CURL_GLOBAL_ALL); - curlWrapper_ = detail::make_unique(); + curlWrapper_ = detail::make_unique(username, password); std::stringstream jobUriStream; jobUriStream << host << ':' << port << "/metrics/job/" << jobname; jobUri_ = jobUriStream.str(); - if (!username.empty()) { - auth_ = username + ":" + password; - } - std::stringstream labelStream; for (auto& label : labels) { labelStream << "/" << label.first << "/" << label.second; @@ -65,7 +36,7 @@ Gateway::Gateway(const std::string& host, const std::string& port, labels_ = labelStream.str(); } -Gateway::~Gateway() { curl_global_cleanup(); } +Gateway::~Gateway() = default; const Gateway::Labels Gateway::GetInstanceLabel(std::string hostname) { if (hostname.empty()) { @@ -88,63 +59,6 @@ void Gateway::RegisterCollectable(const std::weak_ptr& collectable, collectables_.push_back(std::make_pair(collectable, ss.str())); } -int Gateway::performHttpRequest(HttpMethod method, const std::string& uri, - const std::string& body) { - std::lock_guard l(mutex_); - - auto curl = curlWrapper_->curl(); - if (!curl) { - return -CURLE_FAILED_INIT; - } - - curl_easy_reset(curl); - curl_easy_setopt(curl, CURLOPT_URL, uri.c_str()); - - curl_slist* header_chunk = nullptr; - header_chunk = curl_slist_append(header_chunk, CONTENT_TYPE); - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_chunk); - - if (!body.empty()) { - curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.size()); - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.data()); - } - - if (!auth_.empty()) { - curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); - curl_easy_setopt(curl, CURLOPT_USERPWD, auth_.c_str()); - } - - switch (method) { - case HttpMethod::Post: - curl_easy_setopt(curl, CURLOPT_POST, 1L); - break; - - case HttpMethod::Put: - curl_easy_setopt(curl, CURLOPT_NOBODY, 0L); - curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); - break; - - case HttpMethod::Delete: - curl_easy_setopt(curl, CURLOPT_HTTPGET, 0L); - curl_easy_setopt(curl, CURLOPT_NOBODY, 0L); - curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE"); - break; - } - - auto curl_error = curl_easy_perform(curl); - - long response_code; - curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); - - curl_slist_free_all(header_chunk); - - if (curl_error != CURLE_OK) { - return -curl_error; - } - - return response_code; -} - std::string Gateway::getUri(const CollectableEntry& collectable) const { std::stringstream uri; uri << jobUri_ << labels_ << collectable.second; @@ -152,11 +66,11 @@ std::string Gateway::getUri(const CollectableEntry& collectable) const { return uri.str(); } -int Gateway::Push() { return push(HttpMethod::Post); } +int Gateway::Push() { return push(detail::HttpMethod::Post); } -int Gateway::PushAdd() { return push(HttpMethod::Put); } +int Gateway::PushAdd() { return push(detail::HttpMethod::Put); } -int Gateway::push(HttpMethod method) { +int Gateway::push(detail::HttpMethod method) { const auto serializer = TextSerializer{}; for (auto& wcollectable : collectables_) { @@ -168,7 +82,7 @@ int Gateway::push(HttpMethod method) { auto metrics = collectable->Collect(); auto body = serializer.Serialize(metrics); auto uri = getUri(wcollectable); - auto status_code = performHttpRequest(method, uri, body); + auto status_code = curlWrapper_->performHttpRequest(method, uri, body); if (status_code < 100 || status_code >= 400) { return status_code; @@ -178,11 +92,15 @@ int Gateway::push(HttpMethod method) { return 200; } -std::future Gateway::AsyncPush() { return async_push(HttpMethod::Post); } +std::future Gateway::AsyncPush() { + return async_push(detail::HttpMethod::Post); +} -std::future Gateway::AsyncPushAdd() { return async_push(HttpMethod::Put); } +std::future Gateway::AsyncPushAdd() { + return async_push(detail::HttpMethod::Put); +} -std::future Gateway::async_push(HttpMethod method) { +std::future Gateway::async_push(detail::HttpMethod method) { const auto serializer = TextSerializer{}; std::vector> futures; @@ -197,7 +115,7 @@ std::future Gateway::async_push(HttpMethod method) { auto uri = getUri(wcollectable); futures.push_back(std::async(std::launch::async, [method, uri, body, this] { - return performHttpRequest(method, uri, *body); + return curlWrapper_->performHttpRequest(method, uri, *body); })); } @@ -219,7 +137,8 @@ std::future Gateway::async_push(HttpMethod method) { } int Gateway::Delete() { - return performHttpRequest(HttpMethod::Delete, jobUri_, {}); + return curlWrapper_->performHttpRequest(detail::HttpMethod::Delete, jobUri_, + {}); } std::future Gateway::AsyncDelete() { From 7aaecba2c3f14540fed794d9f1c811e4ee44585e Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Fri, 12 Nov 2021 10:01:50 +0100 Subject: [PATCH 195/206] fix(push): Lock access to collectables_ --- push/include/prometheus/gateway.h | 2 ++ push/src/gateway.cc | 3 +++ 2 files changed, 5 insertions(+) diff --git a/push/include/prometheus/gateway.h b/push/include/prometheus/gateway.h index 665a858b..c139320d 100644 --- a/push/include/prometheus/gateway.h +++ b/push/include/prometheus/gateway.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -57,6 +58,7 @@ class PROMETHEUS_CPP_PUSH_EXPORT Gateway { std::string jobUri_; std::string labels_; std::unique_ptr curlWrapper_; + std::mutex mutex_; using CollectableEntry = std::pair, std::string>; std::vector collectables_; diff --git a/push/src/gateway.cc b/push/src/gateway.cc index f1b8ef73..e7acf13a 100644 --- a/push/src/gateway.cc +++ b/push/src/gateway.cc @@ -55,6 +55,7 @@ void Gateway::RegisterCollectable(const std::weak_ptr& collectable, } } + std::lock_guard lock{mutex_}; CleanupStalePointers(collectables_); collectables_.push_back(std::make_pair(collectable, ss.str())); } @@ -73,6 +74,7 @@ int Gateway::PushAdd() { return push(detail::HttpMethod::Put); } int Gateway::push(detail::HttpMethod method) { const auto serializer = TextSerializer{}; + std::lock_guard lock{mutex_}; for (auto& wcollectable : collectables_) { auto collectable = wcollectable.first.lock(); if (!collectable) { @@ -104,6 +106,7 @@ std::future Gateway::async_push(detail::HttpMethod method) { const auto serializer = TextSerializer{}; std::vector> futures; + std::lock_guard lock{mutex_}; for (auto& wcollectable : collectables_) { auto collectable = wcollectable.first.lock(); if (!collectable) { From 1b01f361563bddd4b42ff04212390dd4ee978740 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Fri, 12 Nov 2021 19:02:22 +0100 Subject: [PATCH 196/206] fix(core): gracefully handle label hash collisions ``` before: BM_Registry_CreateFamily 49.2 ns 49.0 ns 11087352 BM_Registry_CreateCounter/0 165 ns 165 ns 4170191 BM_Registry_CreateCounter/1 1967 ns 1958 ns 556346 BM_Registry_CreateCounter/8 4280 ns 4269 ns 176711 BM_Registry_CreateCounter/64 27091 ns 27009 ns 25755 BM_Registry_CreateCounter/512 224201 ns 223581 ns 3023 BM_Registry_CreateCounter/4096 2056280 ns 2049876 ns 330 after: BM_Registry_CreateFamily 47.8 ns 47.8 ns 15131733 BM_Registry_CreateCounter/0 158 ns 158 ns 4295006 BM_Registry_CreateCounter/1 1009 ns 1009 ns 1169219 BM_Registry_CreateCounter/8 3238 ns 3231 ns 203179 BM_Registry_CreateCounter/64 25989 ns 25949 ns 27008 BM_Registry_CreateCounter/512 211288 ns 211220 ns 3265 BM_Registry_CreateCounter/4096 1960240 ns 1959743 ns 350 ``` Fixes: #532 --- core/include/prometheus/detail/utils.h | 19 ++++---- core/include/prometheus/family.h | 11 +++-- core/src/detail/utils.cc | 3 +- core/src/family.cc | 64 +++++++++++--------------- core/tests/utils_test.cc | 20 +++++--- 5 files changed, 59 insertions(+), 58 deletions(-) diff --git a/core/include/prometheus/detail/utils.h b/core/include/prometheus/detail/utils.h index 26d080a3..74572dad 100644 --- a/core/include/prometheus/detail/utils.h +++ b/core/include/prometheus/detail/utils.h @@ -7,17 +7,18 @@ #include "prometheus/detail/core_export.h" namespace prometheus { - namespace detail { -/// \brief Compute the hash value of a map of labels. -/// -/// \param labels The map that will be computed the hash value. -/// -/// \returns The hash value of the given labels. -PROMETHEUS_CPP_CORE_EXPORT std::size_t hash_labels( - const std::map& labels); +/// \brief Label hasher for use in STL containers. +struct PROMETHEUS_CPP_CORE_EXPORT LabelHasher { + /// \brief Compute the hash value of a map of labels. + /// + /// \param labels The map that will be computed the hash value. + /// + /// \returns The hash value of the given labels. + std::size_t operator()( + const std::map& labels) const; +}; } // namespace detail - } // namespace prometheus diff --git a/core/include/prometheus/family.h b/core/include/prometheus/family.h index 93ed021c..1d8083ee 100644 --- a/core/include/prometheus/family.h +++ b/core/include/prometheus/family.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include @@ -12,6 +11,7 @@ #include "prometheus/collectable.h" #include "prometheus/detail/core_export.h" #include "prometheus/detail/future_std.h" +#include "prometheus/detail/utils.h" #include "prometheus/metric_family.h" // IWYU pragma: no_include "prometheus/counter.h" @@ -142,16 +142,17 @@ class PROMETHEUS_CPP_CORE_EXPORT Family : public Collectable { std::vector Collect() const override; private: - std::unordered_map> metrics_; - std::unordered_map> labels_; - std::unordered_map labels_reverse_lookup_; + std::unordered_map, std::unique_ptr, + detail::LabelHasher> + metrics_; const std::string name_; const std::string help_; const std::map constant_labels_; mutable std::mutex mutex_; - ClientMetric CollectMetric(std::size_t hash, T* metric) const; + ClientMetric CollectMetric(const std::map& labels, + T* metric) const; T& Add(const std::map& labels, std::unique_ptr object); }; diff --git a/core/src/detail/utils.cc b/core/src/detail/utils.cc index c8b08ccb..88f511b5 100644 --- a/core/src/detail/utils.cc +++ b/core/src/detail/utils.cc @@ -8,7 +8,8 @@ namespace prometheus { namespace detail { -std::size_t hash_labels(const std::map& labels) { +std::size_t LabelHasher::operator()( + const std::map& labels) const { size_t seed = 0; for (auto& label : labels) { hash_combine(&seed, label.first, label.second); diff --git a/core/src/family.cc b/core/src/family.cc index 90314404..b697c039 100644 --- a/core/src/family.cc +++ b/core/src/family.cc @@ -8,7 +8,6 @@ #include "prometheus/check_names.h" #include "prometheus/counter.h" -#include "prometheus/detail/utils.h" #include "prometheus/gauge.h" #include "prometheus/histogram.h" #include "prometheus/summary.h" @@ -33,55 +32,47 @@ Family::Family(const std::string& name, const std::string& help, template T& Family::Add(const std::map& labels, std::unique_ptr object) { - const auto hash = detail::hash_labels(labels); std::lock_guard lock{mutex_}; - auto metrics_iter = metrics_.find(hash); - - if (metrics_iter != metrics_.end()) { -#ifndef NDEBUG - auto labels_iter = labels_.find(hash); - assert(labels_iter != labels_.end()); - const auto& old_labels = labels_iter->second; - assert(labels == old_labels); -#endif - return *metrics_iter->second; - } - for (auto& label_pair : labels) { - const auto& label_name = label_pair.first; - if (!CheckLabelName(label_name)) { - throw std::invalid_argument("Invalid label name"); - } - if (constant_labels_.count(label_name)) { - throw std::invalid_argument("Duplicate label name"); + auto insert_result = + metrics_.insert(std::make_pair(labels, std::move(object))); + + if (insert_result.second) { + // insertion took place, retroactively check for unlikely issues + for (auto& label_pair : labels) { + const auto& label_name = label_pair.first; + if (!CheckLabelName(label_name)) { + metrics_.erase(insert_result.first); + throw std::invalid_argument("Invalid label name"); + } + if (constant_labels_.count(label_name)) { + metrics_.erase(insert_result.first); + throw std::invalid_argument("Duplicate label name"); + } } } - const auto metric = metrics_.insert(std::make_pair(hash, std::move(object))); - assert(metric.second); - labels_.insert({hash, labels}); - labels_reverse_lookup_.insert({metric.first->second.get(), hash}); - return *(metric.first->second); + auto& stored_object = insert_result.first->second; + assert(stored_object); + return *stored_object; } template void Family::Remove(T* metric) { std::lock_guard lock{mutex_}; - if (labels_reverse_lookup_.count(metric) == 0) { - return; - } - const auto hash = labels_reverse_lookup_.at(metric); - metrics_.erase(hash); - labels_.erase(hash); - labels_reverse_lookup_.erase(metric); + for (auto it = metrics_.begin(); it != metrics_.end(); ++it) { + if (it->second.get() == metric) { + metrics_.erase(it); + break; + } + } } template bool Family::Has(const std::map& labels) const { - const auto hash = detail::hash_labels(labels); std::lock_guard lock{mutex_}; - return metrics_.find(hash) != metrics_.end(); + return metrics_.count(labels) != 0u; } template @@ -114,8 +105,10 @@ std::vector Family::Collect() const { } template -ClientMetric Family::CollectMetric(std::size_t hash, T* metric) const { +ClientMetric Family::CollectMetric( + const std::map& metric_labels, T* metric) const { auto collected = metric->Collect(); + collected.label.reserve(constant_labels_.size() + metric_labels.size()); const auto add_label = [&collected](const std::pair& label_pair) { auto label = ClientMetric::Label{}; @@ -124,7 +117,6 @@ ClientMetric Family::CollectMetric(std::size_t hash, T* metric) const { collected.label.push_back(std::move(label)); }; std::for_each(constant_labels_.cbegin(), constant_labels_.cend(), add_label); - const auto& metric_labels = labels_.at(hash); std::for_each(metric_labels.cbegin(), metric_labels.cend(), add_label); return collected; } diff --git a/core/tests/utils_test.cc b/core/tests/utils_test.cc index 76451f65..701890c0 100644 --- a/core/tests/utils_test.cc +++ b/core/tests/utils_test.cc @@ -9,26 +9,32 @@ namespace prometheus { namespace { -TEST(UtilsTest, hash_labels_1) { +class UtilsTest : public testing::Test { + public: + detail::LabelHasher hasher; +}; + +TEST_F(UtilsTest, hash_labels_1) { std::map labels; labels.insert(std::make_pair("key1", "value1")); labels.insert(std::make_pair("key2", "vaule2")); - auto value1 = detail::hash_labels(labels); - auto value2 = detail::hash_labels(labels); + + auto value1 = hasher(labels); + auto value2 = hasher(labels); EXPECT_EQ(value1, value2); } -TEST(UtilsTest, hash_labels_2) { +TEST_F(UtilsTest, hash_labels_2) { std::map labels1{{"aa", "bb"}}; std::map labels2{{"a", "abb"}}; - EXPECT_NE(detail::hash_labels(labels1), detail::hash_labels(labels2)); + EXPECT_NE(hasher(labels1), hasher(labels2)); } -TEST(UtilsTest, hash_label_3) { +TEST_F(UtilsTest, hash_label_3) { std::map labels1{{"a", "a"}}; std::map labels2{{"aa", ""}}; - EXPECT_NE(detail::hash_labels(labels1), detail::hash_labels(labels2)); + EXPECT_NE(hasher(labels1), hasher(labels2)); } } // namespace From 3202b370203432bcc4651e159db0d9e6f9d1ed42 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 14 Nov 2021 17:13:01 +0100 Subject: [PATCH 197/206] feat(core)!: remove nonstandard append mode --- core/include/prometheus/registry.h | 4 ---- core/src/registry.cc | 14 ++++++-------- core/tests/registry_test.cc | 17 ----------------- 3 files changed, 6 insertions(+), 29 deletions(-) diff --git a/core/include/prometheus/registry.h b/core/include/prometheus/registry.h index 2ca183f2..305eed09 100644 --- a/core/include/prometheus/registry.h +++ b/core/include/prometheus/registry.h @@ -50,10 +50,6 @@ class PROMETHEUS_CPP_CORE_EXPORT Registry : public Collectable { Merge, /// \brief Throws if a family with the same name already exists. Throw, - /// \brief Never merge and always create a new family. This violates the - /// prometheus specification but was the default behavior in earlier - /// versions - NonStandardAppend, }; /// \brief name Create a new registry. diff --git a/core/src/registry.cc b/core/src/registry.cc index ad565d35..7070d928 100644 --- a/core/src/registry.cc +++ b/core/src/registry.cc @@ -120,15 +120,13 @@ Family& Registry::Add(const std::string& name, const std::string& help, } } - if (insert_behavior_ != InsertBehavior::NonStandardAppend) { - auto same_name = [&name](const std::unique_ptr>& family) { - return name == family->GetName(); - }; + auto same_name = [&name](const std::unique_ptr>& family) { + return name == family->GetName(); + }; - auto it = std::find_if(families.begin(), families.end(), same_name); - if (it != families.end()) { - throw std::invalid_argument("Family name already exists"); - } + auto it = std::find_if(families.begin(), families.end(), same_name); + if (it != families.end()) { + throw std::invalid_argument("Family name already exists"); } auto family = detail::make_unique>(name, help, labels); diff --git a/core/tests/registry_test.cc b/core/tests/registry_test.cc index 69937074..a346525f 100644 --- a/core/tests/registry_test.cc +++ b/core/tests/registry_test.cc @@ -81,23 +81,6 @@ TEST(RegistryTest, reject_different_type_than_summary) { EXPECT_ANY_THROW(BuildHistogram().Name(same_name).Register(registry)); } -TEST(RegistryTest, append_same_families) { - Registry registry{Registry::InsertBehavior::NonStandardAppend}; - - std::size_t loops = 4; - - while (loops-- > 0) { - BuildCounter() - .Name("counter") - .Help("Test Counter") - .Register(registry) - .Add({{"name", "test_counter"}}); - } - - auto collected = registry.Collect(); - EXPECT_EQ(4U, collected.size()); -} - TEST(RegistryTest, throw_for_same_family_name) { const auto same_name = std::string{"same_name"}; Registry registry{Registry::InsertBehavior::Throw}; From 91dd416d7636342df57cf2064453f91e3bfda464 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 14 Nov 2021 17:40:26 +0100 Subject: [PATCH 198/206] chore(core): Introduce Labels type --- core/benchmarks/benchmark_helpers.cc | 6 ++--- core/benchmarks/benchmark_helpers.h | 6 ++--- core/benchmarks/counter_bench.cc | 2 -- core/benchmarks/gauge_bench.cc | 2 -- core/benchmarks/histogram_bench.cc | 1 - core/benchmarks/summary_bench.cc | 1 - core/include/prometheus/counter.h | 2 +- core/include/prometheus/detail/builder.h | 7 ++--- core/include/prometheus/detail/utils.h | 6 ++--- core/include/prometheus/family.h | 22 +++++++--------- core/include/prometheus/gauge.h | 2 +- core/include/prometheus/histogram.h | 2 +- core/include/prometheus/labels.h | 11 ++++++++ core/include/prometheus/registry.h | 4 +-- core/include/prometheus/summary.h | 2 +- core/src/detail/builder.cc | 3 +-- core/src/detail/utils.cc | 4 +-- core/src/family.cc | 14 +++++----- core/src/registry.cc | 26 +++++++++---------- core/tests/builder_test.cc | 5 ++-- core/tests/family_test.cc | 8 +++--- core/tests/serializer_test.cc | 1 - core/tests/utils_test.cc | 21 +++++---------- pull/tests/integration/sample_server_multi.cc | 1 - push/include/prometheus/gateway.h | 6 ++--- push/src/gateway.cc | 7 ++--- 26 files changed, 80 insertions(+), 92 deletions(-) create mode 100644 core/include/prometheus/labels.h diff --git a/core/benchmarks/benchmark_helpers.cc b/core/benchmarks/benchmark_helpers.cc index dc6ccea4..78f719c2 100644 --- a/core/benchmarks/benchmark_helpers.cc +++ b/core/benchmarks/benchmark_helpers.cc @@ -2,6 +2,7 @@ #include #include +#include std::string GenerateRandomString(std::size_t length) { auto randchar = []() -> char { @@ -14,10 +15,9 @@ std::string GenerateRandomString(std::size_t length) { return str; } -std::map GenerateRandomLabels( - std::size_t number_of_pairs) { +prometheus::Labels GenerateRandomLabels(std::size_t number_of_pairs) { const auto label_character_count = 10; - auto label_pairs = std::map{}; + auto label_pairs = prometheus::Labels{}; for (std::size_t i = 0; i < number_of_pairs; i++) { label_pairs.insert({GenerateRandomString(label_character_count), GenerateRandomString(label_character_count)}); diff --git a/core/benchmarks/benchmark_helpers.h b/core/benchmarks/benchmark_helpers.h index 99cbeb03..51866764 100644 --- a/core/benchmarks/benchmark_helpers.h +++ b/core/benchmarks/benchmark_helpers.h @@ -1,9 +1,9 @@ #pragma once #include -#include #include +#include "prometheus/labels.h" + std::string GenerateRandomString(std::size_t length); -std::map GenerateRandomLabels( - std::size_t number_of_labels); +prometheus::Labels GenerateRandomLabels(std::size_t number_of_labels); diff --git a/core/benchmarks/counter_bench.cc b/core/benchmarks/counter_bench.cc index 620546f9..be060386 100644 --- a/core/benchmarks/counter_bench.cc +++ b/core/benchmarks/counter_bench.cc @@ -1,7 +1,5 @@ #include -#include - #include "prometheus/counter.h" #include "prometheus/family.h" #include "prometheus/registry.h" diff --git a/core/benchmarks/gauge_bench.cc b/core/benchmarks/gauge_bench.cc index d0c61f53..87bcec56 100644 --- a/core/benchmarks/gauge_bench.cc +++ b/core/benchmarks/gauge_bench.cc @@ -1,7 +1,5 @@ #include -#include - #include "prometheus/family.h" #include "prometheus/gauge.h" #include "prometheus/registry.h" diff --git a/core/benchmarks/histogram_bench.cc b/core/benchmarks/histogram_bench.cc index 9c447474..9bcbb6c0 100644 --- a/core/benchmarks/histogram_bench.cc +++ b/core/benchmarks/histogram_bench.cc @@ -3,7 +3,6 @@ #include #include #include -#include #include #include "prometheus/family.h" diff --git a/core/benchmarks/summary_bench.cc b/core/benchmarks/summary_bench.cc index da80811f..1a73807c 100644 --- a/core/benchmarks/summary_bench.cc +++ b/core/benchmarks/summary_bench.cc @@ -4,7 +4,6 @@ #include #include #include -#include #include #include "prometheus/family.h" diff --git a/core/include/prometheus/counter.h b/core/include/prometheus/counter.h index c67ddde2..9b2ad19d 100644 --- a/core/include/prometheus/counter.h +++ b/core/include/prometheus/counter.h @@ -72,7 +72,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Counter { /// /// - Name(const std::string&) to set the metric name, /// - Help(const std::string&) to set an additional description. -/// - Label(const std::map&) to assign a set of +/// - Labels(const Labels&) to assign a set of /// key-value pairs (= labels) to the metric. /// /// To finish the configuration of the Counter metric, register it with diff --git a/core/include/prometheus/detail/builder.h b/core/include/prometheus/detail/builder.h index f811498f..48f52f89 100644 --- a/core/include/prometheus/detail/builder.h +++ b/core/include/prometheus/detail/builder.h @@ -1,8 +1,9 @@ #pragma once -#include #include +#include "prometheus/labels.h" + // IWYU pragma: private // IWYU pragma: no_include "prometheus/family.h" @@ -17,13 +18,13 @@ namespace detail { template class Builder { public: - Builder& Labels(const std::map& labels); + Builder& Labels(const ::prometheus::Labels& labels); Builder& Name(const std::string&); Builder& Help(const std::string&); Family& Register(Registry&); private: - std::map labels_; + ::prometheus::Labels labels_; std::string name_; std::string help_; }; diff --git a/core/include/prometheus/detail/utils.h b/core/include/prometheus/detail/utils.h index 74572dad..5cea6bda 100644 --- a/core/include/prometheus/detail/utils.h +++ b/core/include/prometheus/detail/utils.h @@ -1,10 +1,9 @@ #pragma once #include -#include -#include #include "prometheus/detail/core_export.h" +#include "prometheus/labels.h" namespace prometheus { namespace detail { @@ -16,8 +15,7 @@ struct PROMETHEUS_CPP_CORE_EXPORT LabelHasher { /// \param labels The map that will be computed the hash value. /// /// \returns The hash value of the given labels. - std::size_t operator()( - const std::map& labels) const; + std::size_t operator()(const Labels& labels) const; }; } // namespace detail diff --git a/core/include/prometheus/family.h b/core/include/prometheus/family.h index 1d8083ee..ef823bdc 100644 --- a/core/include/prometheus/family.h +++ b/core/include/prometheus/family.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include @@ -12,6 +11,7 @@ #include "prometheus/detail/core_export.h" #include "prometheus/detail/future_std.h" #include "prometheus/detail/utils.h" +#include "prometheus/labels.h" #include "prometheus/metric_family.h" // IWYU pragma: no_include "prometheus/counter.h" @@ -89,7 +89,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Family : public Collectable { /// metric. /// \throw std::runtime_exception on invalid metric or label names. Family(const std::string& name, const std::string& help, - const std::map& constant_labels); + const Labels& constant_labels); /// \brief Add a new dimensional data. /// @@ -109,7 +109,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Family : public Collectable { /// labels already exists - the already existing dimensional data. /// \throw std::runtime_exception on invalid label names. template - T& Add(const std::map& labels, Args&&... args) { + T& Add(const Labels& labels, Args&&... args) { return Add(labels, detail::make_unique(args...)); } @@ -122,7 +122,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Family : public Collectable { /// \brief Returns true if the dimensional data with the given labels exist /// /// \param labels A set of key-value pairs (= labels) of the dimensional data. - bool Has(const std::map& labels) const; + bool Has(const Labels& labels) const; /// \brief Returns the name for this family. /// @@ -132,7 +132,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Family : public Collectable { /// \brief Returns the constant labels for this family. /// /// \return All constant labels as key-value pairs. - const std::map GetConstantLabels() const; + const Labels GetConstantLabels() const; /// \brief Returns the current value of each dimensional data. /// @@ -142,19 +142,15 @@ class PROMETHEUS_CPP_CORE_EXPORT Family : public Collectable { std::vector Collect() const override; private: - std::unordered_map, std::unique_ptr, - detail::LabelHasher> - metrics_; + std::unordered_map, detail::LabelHasher> metrics_; const std::string name_; const std::string help_; - const std::map constant_labels_; + const Labels constant_labels_; mutable std::mutex mutex_; - ClientMetric CollectMetric(const std::map& labels, - T* metric) const; - T& Add(const std::map& labels, - std::unique_ptr object); + ClientMetric CollectMetric(const Labels& labels, T* metric) const; + T& Add(const Labels& labels, std::unique_ptr object); }; } // namespace prometheus diff --git a/core/include/prometheus/gauge.h b/core/include/prometheus/gauge.h index 62498376..01d0e07a 100644 --- a/core/include/prometheus/gauge.h +++ b/core/include/prometheus/gauge.h @@ -84,7 +84,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Gauge { /// /// - Name(const std::string&) to set the metric name, /// - Help(const std::string&) to set an additional description. -/// - Label(const std::map&) to assign a set of +/// - Labels(const Labels&) to assign a set of /// key-value pairs (= labels) to the metric. /// /// To finish the configuration of the Gauge metric register it with diff --git a/core/include/prometheus/histogram.h b/core/include/prometheus/histogram.h index a26f8432..fc5fdc27 100644 --- a/core/include/prometheus/histogram.h +++ b/core/include/prometheus/histogram.h @@ -96,7 +96,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Histogram { /// /// - Name(const std::string&) to set the metric name, /// - Help(const std::string&) to set an additional description. -/// - Label(const std::map&) to assign a set of +/// - Labels(const Labels&) to assign a set of /// key-value pairs (= labels) to the metric. /// /// To finish the configuration of the Histogram metric register it with diff --git a/core/include/prometheus/labels.h b/core/include/prometheus/labels.h new file mode 100644 index 00000000..919625b7 --- /dev/null +++ b/core/include/prometheus/labels.h @@ -0,0 +1,11 @@ +#pragma once + +#include +#include + +namespace prometheus { + +/// \brief Multiple labels and their value. +using Labels = std::map; + +} // namespace prometheus diff --git a/core/include/prometheus/registry.h b/core/include/prometheus/registry.h index 305eed09..e21ad9be 100644 --- a/core/include/prometheus/registry.h +++ b/core/include/prometheus/registry.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include @@ -9,6 +8,7 @@ #include "prometheus/collectable.h" #include "prometheus/detail/core_export.h" #include "prometheus/family.h" +#include "prometheus/labels.h" #include "prometheus/metric_family.h" namespace prometheus { @@ -92,7 +92,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Registry : public Collectable { template Family& Add(const std::string& name, const std::string& help, - const std::map& labels); + const Labels& labels); const InsertBehavior insert_behavior_; std::vector>> counters_; diff --git a/core/include/prometheus/summary.h b/core/include/prometheus/summary.h index 87381344..f13b21e7 100644 --- a/core/include/prometheus/summary.h +++ b/core/include/prometheus/summary.h @@ -113,7 +113,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Summary { /// /// - Name(const std::string&) to set the metric name, /// - Help(const std::string&) to set an additional description. -/// - Label(const std::map&) to assign a set of +/// - Labels(const Labels&) to assign a set of /// key-value pairs (= labels) to the metric. /// /// To finish the configuration of the Summary metric register it with diff --git a/core/src/detail/builder.cc b/core/src/detail/builder.cc index 72253834..a1880448 100644 --- a/core/src/detail/builder.cc +++ b/core/src/detail/builder.cc @@ -12,8 +12,7 @@ namespace prometheus { namespace detail { template -Builder& Builder::Labels( - const std::map& labels) { +Builder& Builder::Labels(const ::prometheus::Labels& labels) { labels_ = labels; return *this; } diff --git a/core/src/detail/utils.cc b/core/src/detail/utils.cc index 88f511b5..354dccf0 100644 --- a/core/src/detail/utils.cc +++ b/core/src/detail/utils.cc @@ -1,5 +1,6 @@ #include "prometheus/detail/utils.h" +#include #include #include "hash.h" @@ -8,8 +9,7 @@ namespace prometheus { namespace detail { -std::size_t LabelHasher::operator()( - const std::map& labels) const { +std::size_t LabelHasher::operator()(const Labels& labels) const { size_t seed = 0; for (auto& label : labels) { hash_combine(&seed, label.first, label.second); diff --git a/core/src/family.cc b/core/src/family.cc index b697c039..ed7c4346 100644 --- a/core/src/family.cc +++ b/core/src/family.cc @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -16,7 +17,7 @@ namespace prometheus { template Family::Family(const std::string& name, const std::string& help, - const std::map& constant_labels) + const Labels& constant_labels) : name_(name), help_(help), constant_labels_(constant_labels) { if (!CheckMetricName(name_)) { throw std::invalid_argument("Invalid metric name"); @@ -30,8 +31,7 @@ Family::Family(const std::string& name, const std::string& help, } template -T& Family::Add(const std::map& labels, - std::unique_ptr object) { +T& Family::Add(const Labels& labels, std::unique_ptr object) { std::lock_guard lock{mutex_}; auto insert_result = @@ -70,7 +70,7 @@ void Family::Remove(T* metric) { } template -bool Family::Has(const std::map& labels) const { +bool Family::Has(const Labels& labels) const { std::lock_guard lock{mutex_}; return metrics_.count(labels) != 0u; } @@ -81,7 +81,7 @@ const std::string& Family::GetName() const { } template -const std::map Family::GetConstantLabels() const { +const Labels Family::GetConstantLabels() const { return constant_labels_; } @@ -105,8 +105,8 @@ std::vector Family::Collect() const { } template -ClientMetric Family::CollectMetric( - const std::map& metric_labels, T* metric) const { +ClientMetric Family::CollectMetric(const Labels& metric_labels, + T* metric) const { auto collected = metric->Collect(); collected.label.reserve(constant_labels_.size() + metric_labels.size()); const auto add_label = diff --git a/core/src/registry.cc b/core/src/registry.cc index 7070d928..31bed129 100644 --- a/core/src/registry.cc +++ b/core/src/registry.cc @@ -96,7 +96,7 @@ bool Registry::NameExistsInOtherType(const std::string& name) const { template Family& Registry::Add(const std::string& name, const std::string& help, - const std::map& labels) { + const Labels& labels) { std::lock_guard lock{mutex_}; if (NameExistsInOtherType(name)) { @@ -135,20 +135,20 @@ Family& Registry::Add(const std::string& name, const std::string& help, return ref; } -template Family& Registry::Add( - const std::string& name, const std::string& help, - const std::map& labels); +template Family& Registry::Add(const std::string& name, + const std::string& help, + const Labels& labels); -template Family& Registry::Add( - const std::string& name, const std::string& help, - const std::map& labels); +template Family& Registry::Add(const std::string& name, + const std::string& help, + const Labels& labels); -template Family& Registry::Add( - const std::string& name, const std::string& help, - const std::map& labels); +template Family& Registry::Add(const std::string& name, + const std::string& help, + const Labels& labels); -template Family& Registry::Add( - const std::string& name, const std::string& help, - const std::map& labels); +template Family& Registry::Add(const std::string& name, + const std::string& help, + const Labels& labels); } // namespace prometheus diff --git a/core/tests/builder_test.cc b/core/tests/builder_test.cc index ce460d73..e3764f04 100644 --- a/core/tests/builder_test.cc +++ b/core/tests/builder_test.cc @@ -14,6 +14,7 @@ #include "prometheus/family.h" #include "prometheus/gauge.h" #include "prometheus/histogram.h" +#include "prometheus/labels.h" #include "prometheus/registry.h" #include "prometheus/summary.h" @@ -53,8 +54,8 @@ class BuilderTest : public testing::Test { const std::string name = "some_name"; const std::string help = "Additional description."; - const std::map const_labels = {{"key", "value"}}; - const std::map more_labels = {{"name", "test"}}; + const Labels const_labels = {{"key", "value"}}; + const Labels more_labels = {{"name", "test"}}; const std::vector expected_labels = getExpectedLabels(); }; diff --git a/core/tests/family_test.cc b/core/tests/family_test.cc index 37f6d139..6b08bd36 100644 --- a/core/tests/family_test.cc +++ b/core/tests/family_test.cc @@ -9,6 +9,7 @@ #include "prometheus/counter.h" #include "prometheus/detail/future_std.h" #include "prometheus/histogram.h" +#include "prometheus/labels.h" namespace prometheus { namespace { @@ -29,7 +30,7 @@ TEST(FamilyTest, labels) { } TEST(FamilyTest, reject_same_label_keys) { - auto labels = std::map{{"component", "test"}}; + auto labels = Labels{{"component", "test"}}; Family family{"total_requests", "Counts all requests", labels}; EXPECT_ANY_THROW(family.Add(labels)); @@ -80,8 +81,7 @@ TEST(FamilyTest, add_twice) { TEST(FamilyTest, throw_on_invalid_metric_name) { auto create_family_with_invalid_name = []() { - return detail::make_unique>( - "", "empty name", std::map{}); + return detail::make_unique>("", "empty name", Labels{}); }; EXPECT_ANY_THROW(create_family_with_invalid_name()); } @@ -90,7 +90,7 @@ TEST(FamilyTest, throw_on_invalid_constant_label_name) { auto create_family_with_invalid_labels = []() { return detail::make_unique>( "total_requests", "Counts all requests", - std::map{{"__inavlid", "counter1"}}); + Labels{{"__inavlid", "counter1"}}); }; EXPECT_ANY_THROW(create_family_with_invalid_labels()); } diff --git a/core/tests/serializer_test.cc b/core/tests/serializer_test.cc index cdb5a9c5..ebf8fd73 100644 --- a/core/tests/serializer_test.cc +++ b/core/tests/serializer_test.cc @@ -4,7 +4,6 @@ #include #include #include -#include #include #include "prometheus/counter.h" diff --git a/core/tests/utils_test.cc b/core/tests/utils_test.cc index 701890c0..b3c1f4f7 100644 --- a/core/tests/utils_test.cc +++ b/core/tests/utils_test.cc @@ -2,9 +2,6 @@ #include -#include -#include - namespace prometheus { namespace { @@ -15,25 +12,19 @@ class UtilsTest : public testing::Test { }; TEST_F(UtilsTest, hash_labels_1) { - std::map labels; - labels.insert(std::make_pair("key1", "value1")); - labels.insert(std::make_pair("key2", "vaule2")); - - auto value1 = hasher(labels); - auto value2 = hasher(labels); - - EXPECT_EQ(value1, value2); + Labels labels{{"key1", "value1"}, {"key2", "vaule2"}}; + EXPECT_EQ(hasher(labels), hasher(labels)); } TEST_F(UtilsTest, hash_labels_2) { - std::map labels1{{"aa", "bb"}}; - std::map labels2{{"a", "abb"}}; + Labels labels1{{"aa", "bb"}}; + Labels labels2{{"a", "abb"}}; EXPECT_NE(hasher(labels1), hasher(labels2)); } TEST_F(UtilsTest, hash_label_3) { - std::map labels1{{"a", "a"}}; - std::map labels2{{"aa", ""}}; + Labels labels1{{"a", "a"}}; + Labels labels2{{"aa", ""}}; EXPECT_NE(hasher(labels1), hasher(labels2)); } diff --git a/pull/tests/integration/sample_server_multi.cc b/pull/tests/integration/sample_server_multi.cc index 9e9f41b0..801f1b9d 100644 --- a/pull/tests/integration/sample_server_multi.cc +++ b/pull/tests/integration/sample_server_multi.cc @@ -1,6 +1,5 @@ #include #include -#include #include #include "prometheus/client_metric.h" diff --git a/push/include/prometheus/gateway.h b/push/include/prometheus/gateway.h index c139320d..202ed284 100644 --- a/push/include/prometheus/gateway.h +++ b/push/include/prometheus/gateway.h @@ -1,7 +1,6 @@ #pragma once #include -#include #include #include #include @@ -11,6 +10,7 @@ #include "prometheus/collectable.h" #include "prometheus/detail/http_method.h" #include "prometheus/detail/push_export.h" +#include "prometheus/labels.h" namespace prometheus { @@ -20,8 +20,6 @@ class CurlWrapper; class PROMETHEUS_CPP_PUSH_EXPORT Gateway { public: - using Labels = std::map; - Gateway(const std::string& host, const std::string& port, const std::string& jobname, const Labels& labels = {}, const std::string& username = {}, const std::string& password = {}); @@ -36,7 +34,7 @@ class PROMETHEUS_CPP_PUSH_EXPORT Gateway { void RegisterCollectable(const std::weak_ptr& collectable, const Labels* labels = nullptr); - static const Labels GetInstanceLabel(std::string hostname); + static Labels GetInstanceLabel(std::string hostname); // Push metrics to the given pushgateway. int Push(); diff --git a/push/src/gateway.cc b/push/src/gateway.cc index e7acf13a..c2633a2f 100644 --- a/push/src/gateway.cc +++ b/push/src/gateway.cc @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -38,11 +39,11 @@ Gateway::Gateway(const std::string& host, const std::string& port, Gateway::~Gateway() = default; -const Gateway::Labels Gateway::GetInstanceLabel(std::string hostname) { +Labels Gateway::GetInstanceLabel(std::string hostname) { if (hostname.empty()) { - return Gateway::Labels{}; + return Labels{}; } - return Gateway::Labels{{"instance", hostname}}; + return Labels{{"instance", hostname}}; } void Gateway::RegisterCollectable(const std::weak_ptr& collectable, From d8b3aa929d789c1e88805f1d1b5808e8d59ac730 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 13 Nov 2021 12:25:20 +0100 Subject: [PATCH 199/206] feat(core): Allow to remove a Family from their Registry Fixes: #498 --- core/include/prometheus/registry.h | 13 +++++++++++++ core/src/registry.cc | 30 ++++++++++++++++++++++++++++++ core/tests/registry_test.cc | 14 ++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/core/include/prometheus/registry.h b/core/include/prometheus/registry.h index e21ad9be..51aeef5d 100644 --- a/core/include/prometheus/registry.h +++ b/core/include/prometheus/registry.h @@ -80,6 +80,19 @@ class PROMETHEUS_CPP_CORE_EXPORT Registry : public Collectable { /// \return Zero or more metrics and their samples. std::vector Collect() const override; + /// \brief Removes a metrics family from the registry. + /// + /// Please note that this operation invalidates the previously + /// returned reference to the Family and all of their added + /// metric objects. + /// + /// \tparam T One of the metric types Counter, Gauge, Histogram or Summary. + /// \param family The family to remove + /// + /// \return True if the family was found and removed. + template + bool Remove(const Family& family); + private: template friend class detail::Builder; diff --git a/core/src/registry.cc b/core/src/registry.cc index 31bed129..690ace44 100644 --- a/core/src/registry.cc +++ b/core/src/registry.cc @@ -151,4 +151,34 @@ template Family& Registry::Add(const std::string& name, const std::string& help, const Labels& labels); +template +bool Registry::Remove(const Family& family) { + std::lock_guard lock{mutex_}; + + auto& families = GetFamilies(); + auto same_family = [&family](const std::unique_ptr>& in) { + return &family == in.get(); + }; + + auto it = std::find_if(families.begin(), families.end(), same_family); + if (it == families.end()) { + return false; + } + + families.erase(it); + return true; +} + +template bool PROMETHEUS_CPP_CORE_EXPORT +Registry::Remove(const Family& family); + +template bool PROMETHEUS_CPP_CORE_EXPORT +Registry::Remove(const Family& family); + +template bool PROMETHEUS_CPP_CORE_EXPORT +Registry::Remove(const Family& family); + +template bool PROMETHEUS_CPP_CORE_EXPORT +Registry::Remove(const Family& family); + } // namespace prometheus diff --git a/core/tests/registry_test.cc b/core/tests/registry_test.cc index a346525f..994491e4 100644 --- a/core/tests/registry_test.cc +++ b/core/tests/registry_test.cc @@ -41,6 +41,20 @@ TEST(RegistryTest, build_histogram_family) { ASSERT_EQ(collected.size(), 1U); } +TEST(RegistryTest, unable_to_remove_family) { + Family family{"name", "help", {}}; + Registry registry{}; + EXPECT_FALSE(registry.Remove(family)); +} + +TEST(RegistryTest, remove_and_readd_family) { + Registry registry{Registry::InsertBehavior::Throw}; + + auto& counter = BuildCounter().Name("name").Register(registry); + EXPECT_TRUE(registry.Remove(counter)); + EXPECT_NO_THROW(BuildCounter().Name("name").Register(registry)); +} + TEST(RegistryTest, reject_different_type_than_counter) { const auto same_name = std::string{"same_name"}; Registry registry{}; From 207139d51b771c3c0116cd90e515fa8e484bff18 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Mon, 15 Nov 2021 21:14:36 +0100 Subject: [PATCH 200/206] fix(push): remove unused variable --- push/src/gateway.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/push/src/gateway.cc b/push/src/gateway.cc index c2633a2f..205a3196 100644 --- a/push/src/gateway.cc +++ b/push/src/gateway.cc @@ -18,9 +18,6 @@ namespace prometheus { -static const char CONTENT_TYPE[] = - "Content-Type: text/plain; version=0.0.4; charset=utf-8"; - Gateway::Gateway(const std::string& host, const std::string& port, const std::string& jobname, const Labels& labels, const std::string& username, const std::string& password) { From 4ea303fa66e4c26dc4df67045fa0edf09c2f3077 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Tue, 16 Nov 2021 21:51:22 +0100 Subject: [PATCH 201/206] feat(push): Add method to delete metrics for instance Fixes: #303 --- push/include/prometheus/gateway.h | 6 ++++++ push/src/gateway.cc | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/push/include/prometheus/gateway.h b/push/include/prometheus/gateway.h index 202ed284..e6acd0f0 100644 --- a/push/include/prometheus/gateway.h +++ b/push/include/prometheus/gateway.h @@ -52,6 +52,12 @@ class PROMETHEUS_CPP_PUSH_EXPORT Gateway { // Delete metrics from the given pushgateway. std::future AsyncDelete(); + // Delete metrics from the given pushgateway (for configured instance labels). + int DeleteForInstance(); + + // Delete metrics from the given pushgateway (for configured instance labels). + std::future AsyncDeleteForInstance(); + private: std::string jobUri_; std::string labels_; diff --git a/push/src/gateway.cc b/push/src/gateway.cc index 205a3196..17cedb2d 100644 --- a/push/src/gateway.cc +++ b/push/src/gateway.cc @@ -146,6 +146,15 @@ std::future Gateway::AsyncDelete() { return std::async(std::launch::async, [&] { return Delete(); }); } +int Gateway::DeleteForInstance() { + return curlWrapper_->performHttpRequest(detail::HttpMethod::Delete, + jobUri_ + labels_, {}); +} + +std::future Gateway::AsyncDeleteForInstance() { + return std::async(std::launch::async, [&] { return DeleteForInstance(); }); +} + void Gateway::CleanupStalePointers( std::vector& collectables) { collectables.erase( From 8f874d478bf91e0eb810b61a993987d98b18e753 Mon Sep 17 00:00:00 2001 From: Anatoly Pashkovich Date: Mon, 7 Feb 2022 15:28:28 +0300 Subject: [PATCH 202/206] fix(push): Allow POST empty data Fixed: #555 --- push/src/curl_wrapper.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/push/src/curl_wrapper.cc b/push/src/curl_wrapper.cc index 37e58564..767e10f1 100644 --- a/push/src/curl_wrapper.cc +++ b/push/src/curl_wrapper.cc @@ -46,6 +46,8 @@ int CurlWrapper::performHttpRequest(HttpMethod method, const std::string& uri, if (!body.empty()) { curl_easy_setopt(curl_, CURLOPT_POSTFIELDSIZE, body.size()); curl_easy_setopt(curl_, CURLOPT_POSTFIELDS, body.data()); + } else { + curl_easy_setopt(curl_, CURLOPT_POSTFIELDSIZE, 0L); } if (!auth_.empty()) { From 7817761ffd3b5c85024a6f6147694a03b4275c3d Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 5 Mar 2022 12:16:37 +0100 Subject: [PATCH 203/206] chore(push): Use curl 7.82.0 --- bazel/repositories.bzl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index 9c0e87fe..1f807da4 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -26,11 +26,11 @@ def prometheus_cpp_repositories(): maybe( http_archive, name = "com_github_curl", - sha256 = "dab997c9b08cb4a636a03f2f7f985eaba33279c1c52692430018fae4a4878dc7", - strip_prefix = "curl-7.80.0", + sha256 = "910cc5fe279dc36e2cca534172c94364cf3fcf7d6494ba56e6c61a390881ddce", + strip_prefix = "curl-7.82.0", urls = [ - "https://github.com/curl/curl/releases/download/curl-7_80_0/curl-7.80.0.tar.gz", - "https://curl.haxx.se/download/curl-7.80.0.tar.gz", + "https://github.com/curl/curl/releases/download/curl-7_82_0/curl-7.82.0.tar.gz", + "https://curl.haxx.se/download/curl-7.82.0.tar.gz", ], build_file = "@com_github_jupp0r_prometheus_cpp//bazel:curl.BUILD", ) From d2c9d38f86a7f82e1a42df2d50a7cb2ec6dbd725 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 5 Mar 2022 12:18:54 +0100 Subject: [PATCH 204/206] chore: Use Google Benchmark 1.6.1 --- bazel/repositories.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index 1f807da4..0fe8e252 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -38,10 +38,10 @@ def prometheus_cpp_repositories(): maybe( http_archive, name = "com_github_google_benchmark", - sha256 = "1f71c72ce08d2c1310011ea6436b31e39ccab8c2db94186d26657d41747c85d6", - strip_prefix = "benchmark-1.6.0", + sha256 = "6132883bc8c9b0df5375b16ab520fac1a85dc9e4cf5be59480448ece74b278d4", + strip_prefix = "benchmark-1.6.1", urls = [ - "https://github.com/google/benchmark/archive/v1.6.0.tar.gz", + "https://github.com/google/benchmark/archive/v1.6.1.tar.gz", ], ) From d3847e514bd82b59f537c60a413b382552793f79 Mon Sep 17 00:00:00 2001 From: Leith Bade Date: Fri, 25 Mar 2022 10:31:56 +1100 Subject: [PATCH 205/206] Fix unused errors --- core/src/counter.cc | 6 +++++- core/src/histogram.cc | 2 ++ core/src/summary.cc | 6 +++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/core/src/counter.cc b/core/src/counter.cc index 987a4c5c..02d720c1 100644 --- a/core/src/counter.cc +++ b/core/src/counter.cc @@ -19,6 +19,10 @@ ClientMetric Counter::Collect() const { return metric; } -bool Counter::Expired(std::time_t time, double seconds) const { return false; } +bool Counter::Expired(std::time_t time, double seconds) const { + (void)time; + (void)seconds; + return false; +} } // namespace prometheus diff --git a/core/src/histogram.cc b/core/src/histogram.cc index a5b3af7e..89e3d738 100644 --- a/core/src/histogram.cc +++ b/core/src/histogram.cc @@ -69,6 +69,8 @@ ClientMetric Histogram::Collect() const { } bool Histogram::Expired(std::time_t time, double seconds) const { + (void)time; + (void)seconds; return false; } diff --git a/core/src/summary.cc b/core/src/summary.cc index 698c3817..2582d90e 100644 --- a/core/src/summary.cc +++ b/core/src/summary.cc @@ -37,6 +37,10 @@ ClientMetric Summary::Collect() const { return metric; } -bool Summary::Expired(std::time_t time, double seconds) const { return false; } +bool Summary::Expired(std::time_t time, double seconds) const { + (void)time; + (void)seconds; + return false; +} } // namespace prometheus From 4605b039e8e8306dafa07e32e1dc8d815a5d5518 Mon Sep 17 00:00:00 2001 From: Leith Bade Date: Wed, 23 Mar 2022 22:59:35 +1100 Subject: [PATCH 206/206] Run IWYU --- core/include/prometheus/detail/builder.h | 1 + core/include/prometheus/family.h | 4 ---- core/include/prometheus/registry.h | 13 +++++++++---- core/src/detail/builder.cc | 1 + core/src/detail/time_window_quantiles.cc | 1 - core/src/detail/utils.cc | 3 --- core/src/family.cc | 1 - core/tests/registry_test.cc | 1 + core/tests/serializer_test.cc | 1 + pull/include/prometheus/exposer.h | 7 ++++--- pull/src/endpoint.h | 4 +++- pull/src/handler.cc | 1 + pull/src/metrics_collector.h | 4 +++- push/include/prometheus/gateway.h | 2 +- push/src/gateway.cc | 1 - 15 files changed, 25 insertions(+), 20 deletions(-) diff --git a/core/include/prometheus/detail/builder.h b/core/include/prometheus/detail/builder.h index 8e4b119f..c145718f 100644 --- a/core/include/prometheus/detail/builder.h +++ b/core/include/prometheus/detail/builder.h @@ -6,6 +6,7 @@ // IWYU pragma: private // IWYU pragma: no_include "prometheus/family.h" +// IWYU pragma: no_include "prometheus/registry.h" namespace prometheus { diff --git a/core/include/prometheus/family.h b/core/include/prometheus/family.h index 71420153..968cead0 100644 --- a/core/include/prometheus/family.h +++ b/core/include/prometheus/family.h @@ -1,10 +1,6 @@ #pragma once -#include -#include -#include #include -#include #include #include #include diff --git a/core/include/prometheus/registry.h b/core/include/prometheus/registry.h index 34f77e1d..9176aefa 100644 --- a/core/include/prometheus/registry.h +++ b/core/include/prometheus/registry.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -11,12 +12,16 @@ #include "prometheus/labels.h" #include "prometheus/metric_family.h" +// IWYU pragma: no_include "prometheus/counter.h" +// IWYU pragma: no_include "prometheus/gauge.h" +// IWYU pragma: no_include "prometheus/histogram.h" +// IWYU pragma: no_include "prometheus/summary.h" namespace prometheus { -class Counter; -class Gauge; -class Histogram; -class Summary; +class Counter; // IWYU pragma: keep +class Gauge; // IWYU pragma: keep +class Histogram; // IWYU pragma: keep +class Summary; // IWYU pragma: keep namespace detail { diff --git a/core/src/detail/builder.cc b/core/src/detail/builder.cc index f0cbbb03..924a8737 100644 --- a/core/src/detail/builder.cc +++ b/core/src/detail/builder.cc @@ -2,6 +2,7 @@ #include "prometheus/counter.h" #include "prometheus/detail/core_export.h" +#include "prometheus/family.h" #include "prometheus/gauge.h" #include "prometheus/histogram.h" #include "prometheus/registry.h" diff --git a/core/src/detail/time_window_quantiles.cc b/core/src/detail/time_window_quantiles.cc index 57f1e1c6..55e48564 100644 --- a/core/src/detail/time_window_quantiles.cc +++ b/core/src/detail/time_window_quantiles.cc @@ -1,7 +1,6 @@ #include "prometheus/detail/time_window_quantiles.h" // IWYU pragma: export #include -#include namespace prometheus { namespace detail { diff --git a/core/src/detail/utils.cc b/core/src/detail/utils.cc index 354dccf0..f605f7c7 100644 --- a/core/src/detail/utils.cc +++ b/core/src/detail/utils.cc @@ -1,8 +1,5 @@ #include "prometheus/detail/utils.h" -#include -#include - #include "hash.h" namespace prometheus { diff --git a/core/src/family.cc b/core/src/family.cc index 934f6537..e4a4145d 100644 --- a/core/src/family.cc +++ b/core/src/family.cc @@ -4,7 +4,6 @@ #include #include #include -#include #include #include "prometheus/check_names.h" diff --git a/core/tests/registry_test.cc b/core/tests/registry_test.cc index 5b899379..9e9b8f9c 100644 --- a/core/tests/registry_test.cc +++ b/core/tests/registry_test.cc @@ -3,6 +3,7 @@ #include #include +#include #include #include "prometheus/counter.h" diff --git a/core/tests/serializer_test.cc b/core/tests/serializer_test.cc index 45568f8c..d9a10761 100644 --- a/core/tests/serializer_test.cc +++ b/core/tests/serializer_test.cc @@ -1,6 +1,7 @@ #include #include +#include #include #include #include diff --git a/pull/include/prometheus/exposer.h b/pull/include/prometheus/exposer.h index 83e0e7f0..601cffb8 100644 --- a/pull/include/prometheus/exposer.h +++ b/pull/include/prometheus/exposer.h @@ -9,14 +9,15 @@ #include "prometheus/collectable.h" #include "prometheus/detail/pull_export.h" +// IWYU pragma: no_include "CivetServer.h" -class CivetServer; -struct CivetCallbacks; +class CivetServer; // IWYU pragma: keep +struct CivetCallbacks; // IWYU pragma: keep namespace prometheus { namespace detail { -class Endpoint; +class Endpoint; // IWYU pragma: keep } // namespace detail class PROMETHEUS_CPP_PULL_EXPORT Exposer { diff --git a/pull/src/endpoint.h b/pull/src/endpoint.h index 81bb48f9..5c4312ae 100644 --- a/pull/src/endpoint.h +++ b/pull/src/endpoint.h @@ -9,9 +9,11 @@ #include "prometheus/collectable.h" #include "prometheus/registry.h" +// IWYU pragma: no_include "handler.h" + namespace prometheus { namespace detail { -class MetricsHandler; +class MetricsHandler; // IWYU pragma: keep class Endpoint { public: diff --git a/pull/src/handler.cc b/pull/src/handler.cc index 5a55001b..da8f7055 100644 --- a/pull/src/handler.cc +++ b/pull/src/handler.cc @@ -2,6 +2,7 @@ #include #include +#include #include #include #include diff --git a/pull/src/metrics_collector.h b/pull/src/metrics_collector.h index 4c3bb614..a6d89a27 100644 --- a/pull/src/metrics_collector.h +++ b/pull/src/metrics_collector.h @@ -5,8 +5,10 @@ #include "prometheus/metric_family.h" +// IWYU pragma: no_include "prometheus/collectable.h" + namespace prometheus { -class Collectable; +class Collectable; // IWYU pragma: keep namespace detail { std::vector CollectMetrics( const std::vector>& collectables); diff --git a/push/include/prometheus/gateway.h b/push/include/prometheus/gateway.h index e6acd0f0..2bdb0de9 100644 --- a/push/include/prometheus/gateway.h +++ b/push/include/prometheus/gateway.h @@ -15,7 +15,7 @@ namespace prometheus { namespace detail { -class CurlWrapper; +class CurlWrapper; // IWYU pragma: keep } class PROMETHEUS_CPP_PUSH_EXPORT Gateway { diff --git a/push/src/gateway.cc b/push/src/gateway.cc index 17cedb2d..15227ec8 100644 --- a/push/src/gateway.cc +++ b/push/src/gateway.cc @@ -3,7 +3,6 @@ #include #include -#include #include #include #include