├── .bazelignore ├── .bazelrc ├── .clang-format ├── .github ├── renovate.json5 └── workflows │ ├── bazel-ci.yml │ ├── cmake-ci.yml │ ├── coverage.yml │ ├── doxygen.yml │ ├── linting.yml │ └── release.yml ├── .gitignore ├── .gitmodules ├── BUILD.bazel ├── CMakeLists.txt ├── LICENSE ├── MODULE.bazel ├── MODULE.bazel.lock ├── README.md ├── WORKSPACE.bzlmod ├── bazel ├── BUILD.bazel ├── dummy_export.h.tpl └── export_header.bzl ├── cmake ├── CheckAtomic.cmake ├── FindTelegraf.cmake ├── civetweb-3rdparty-config.cmake ├── googlemock-3rdparty-config.cmake ├── googletest.imp ├── project-import-cmake │ ├── CMakeLists.txt │ ├── sample_client.cc │ └── sample_server.cc ├── project-import-pkgconfig │ ├── CMakeLists.txt │ ├── sample_client.cc │ └── sample_server.cc ├── prometheus-cpp-config.cmake.in ├── prometheus-cpp-core.pc.in ├── prometheus-cpp-pull.pc.in └── prometheus-cpp-push.pc.in ├── core ├── BUILD.bazel ├── CMakeLists.txt ├── benchmarks │ ├── BUILD.bazel │ ├── CMakeLists.txt │ ├── benchmark_helpers.cc │ ├── benchmark_helpers.h │ ├── counter_bench.cc │ ├── gauge_bench.cc │ ├── histogram_bench.cc │ ├── info_bench.cc │ ├── main.cc │ ├── registry_bench.cc │ └── summary_bench.cc ├── include │ └── prometheus │ │ ├── check_names.h │ │ ├── client_metric.h │ │ ├── collectable.h │ │ ├── counter.h │ │ ├── detail │ │ ├── builder.h │ │ ├── ckms_quantiles.h │ │ ├── future_std.h │ │ ├── time_window_quantiles.h │ │ └── utils.h │ │ ├── family.h │ │ ├── gauge.h │ │ ├── histogram.h │ │ ├── info.h │ │ ├── labels.h │ │ ├── metric_family.h │ │ ├── metric_type.h │ │ ├── registry.h │ │ ├── serializer.h │ │ ├── summary.h │ │ └── text_serializer.h ├── src │ ├── check_names.cc │ ├── counter.cc │ ├── detail │ │ ├── builder.cc │ │ ├── ckms_quantiles.cc │ │ ├── hash.h │ │ ├── time_window_quantiles.cc │ │ └── utils.cc │ ├── family.cc │ ├── gauge.cc │ ├── histogram.cc │ ├── info.cc │ ├── registry.cc │ ├── serializer.cc │ ├── summary.cc │ └── text_serializer.cc └── tests │ ├── BUILD.bazel │ ├── CMakeLists.txt │ ├── builder_test.cc │ ├── check_label_name_test.cc │ ├── check_metric_name_test.cc │ ├── counter_test.cc │ ├── family_test.cc │ ├── gauge_test.cc │ ├── histogram_test.cc │ ├── raii_locale.h │ ├── registry_test.cc │ ├── serializer_test.cc │ ├── summary_test.cc │ ├── text_serializer_test.cc │ └── utils_test.cc ├── doc └── Doxyfile ├── pull ├── BUILD.bazel ├── CMakeLists.txt ├── include │ └── prometheus │ │ └── exposer.h ├── src │ ├── basic_auth.cc │ ├── basic_auth.h │ ├── endpoint.cc │ ├── endpoint.h │ ├── exposer.cc │ ├── handler.cc │ ├── handler.h │ ├── metrics_collector.cc │ └── metrics_collector.h └── tests │ ├── CMakeLists.txt │ ├── integration │ ├── BUILD.bazel │ ├── CMakeLists.txt │ ├── integration_test.cc │ ├── lint.sh │ ├── sample_server.cc │ ├── sample_server_auth.cc │ ├── sample_server_multi.cc │ ├── scrape.conf │ └── scrape.sh │ └── unit │ ├── BUILD.bazel │ ├── CMakeLists.txt │ └── exposer_test.cc ├── push ├── BUILD.bazel ├── CMakeLists.txt ├── include │ └── prometheus │ │ ├── detail │ │ └── http_method.h │ │ └── gateway.h ├── src │ ├── detail │ │ ├── curl_wrapper.cc │ │ ├── curl_wrapper.h │ │ ├── label_encoder.cc │ │ └── label_encoder.h │ └── gateway.cc └── tests │ ├── CMakeLists.txt │ ├── integration │ ├── BUILD.bazel │ ├── CMakeLists.txt │ └── sample_client.cc │ └── internal │ ├── BUILD.bazel │ ├── CMakeLists.txt │ └── label_encoder_test.cc └── util ├── BUILD.bazel ├── CMakeLists.txt ├── include └── prometheus │ └── detail │ └── base64.h └── tests ├── CMakeLists.txt └── unit ├── BUILD.bazel ├── CMakeLists.txt └── base64_test.cc /.bazelignore: -------------------------------------------------------------------------------- 1 | 3rdparty 2 | -------------------------------------------------------------------------------- /.bazelrc: -------------------------------------------------------------------------------- 1 | # Make globs that don't match anything fail 2 | common --incompatible_disallow_empty_glob 3 | 4 | build:asan --strip=never 5 | build:asan --copt -fsanitize=address 6 | build:asan --copt -DADDRESS_SANITIZER 7 | build:asan --copt -O0 8 | build:asan --copt -fno-omit-frame-pointer 9 | build:asan --copt -g 10 | build:asan --linkopt -fsanitize=address 11 | build:asan --cc_output_directory_tag=asan 12 | 13 | build:ssl --define=with_civetweb_ssl=true 14 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Google 2 | DerivePointerAlignment: false 3 | -------------------------------------------------------------------------------- /.github/renovate.json5: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["config:recommended"], 4 | } 5 | -------------------------------------------------------------------------------- /.github/workflows/bazel-ci.yml: -------------------------------------------------------------------------------- 1 | name: Bazel CI 2 | on: 3 | pull_request: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | build: 10 | name: Bazel on ${{ matrix.os }} 11 | runs-on: ${{ matrix.os }} 12 | strategy: 13 | matrix: 14 | os: [macos-latest, ubuntu-latest, windows-latest] 15 | include: 16 | - os: macOS-latest 17 | bazel_args: "--cxxopt=-std=c++17" 18 | - os: ubuntu-latest 19 | bazel_args: "--cxxopt=-std=c++17" 20 | - os: windows-latest 21 | bazel_args: "--cxxopt=/std:c++17" 22 | steps: 23 | - name: Checkout source 24 | uses: actions/checkout@v4 25 | 26 | - name: Generate German locale on Ubuntu 27 | if: runner.os == 'Linux' 28 | run: | 29 | sudo apt-get remove -y --purge man-db # avoid time-consuming trigger 30 | sudo apt-get update 31 | sudo apt-get install -y locales 32 | sudo locale-gen de_DE.UTF-8 # used by SerializerTest 33 | 34 | - name: Install telegraf on macOS 35 | if: runner.os == 'macOS' 36 | run: brew install telegraf 37 | 38 | - name: Build with SSL 39 | if: runner.os != 'macOS' 40 | run: bazel build ${{ matrix.bazel_args }} --config=ssl //... 41 | 42 | - name: Test with SSL 43 | if: runner.os != 'macOS' 44 | run: bazel test ${{ matrix.bazel_args }} --config=ssl --test_output=all //... 45 | 46 | - name: Build 47 | run: bazel build ${{ matrix.bazel_args }} //... 48 | 49 | - name: Test 50 | run: bazel test ${{ matrix.bazel_args }} --test_output=all //... 51 | 52 | - name: Scraping Test 53 | if: runner.os == 'macOS' 54 | run: bazel test ${{ matrix.bazel_args }} --test_output=all //pull/tests/integration:scrape-test 55 | -------------------------------------------------------------------------------- /.github/workflows/coverage.yml: -------------------------------------------------------------------------------- 1 | name: Coverage 2 | on: 3 | pull_request: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | build: 10 | name: Code Coverage 11 | runs-on: ubuntu-24.04 12 | steps: 13 | - name: Checkout source 14 | uses: actions/checkout@v4 15 | 16 | - name: Mount vcpkg cache 17 | uses: actions/cache@v4 18 | with: 19 | path: "~/.cache/vcpkg/archives" 20 | key: vcpkg-${{ runner.os }} 21 | 22 | - name: Install vcpkg dependencies 23 | run: vcpkg install benchmark civetweb curl[core] gtest zlib 24 | 25 | - name: Generate German locale on Ubuntu 26 | if: runner.os == 'Linux' 27 | run: | 28 | sudo apt-get remove -y --purge man-db # avoid time-consuming trigger 29 | sudo apt-get update 30 | sudo apt-get install -y locales 31 | sudo locale-gen de_DE.UTF-8 # used by SerializerTest 32 | 33 | - name: Install ninja on Ubuntu 34 | if: runner.os == 'Linux' 35 | run: | 36 | sudo apt-get install -y ninja-build 37 | 38 | - name: Install lcov 39 | if: runner.os == 'Linux' 40 | run: | 41 | sudo apt-get install -y lcov 42 | 43 | - name: Install lcov 2.3 (which fixes function coverage calculation, https://bugs.launchpad.net/ubuntu/+source/lcov/+bug/2052354) 44 | if: runner.os == 'Linux' 45 | run: | 46 | echo -e "Package: *\nPin: release n=plucky\nPin-Priority: 100" | sudo tee /etc/apt/preferences.d/99-plucky 47 | echo "deb http://azure.archive.ubuntu.com/ubuntu/ plucky main universe" | sudo tee /etc/apt/sources.list.d/ubuntu-plucky.list 48 | sudo apt-get update 49 | sudo apt-get install -y -t plucky lcov 50 | apt-cache policy lcov 51 | 52 | - name: "CMake Configure for Unix with vcpkg dependencies" 53 | env: 54 | CFLAGS: "--coverage" 55 | CXXFLAGS: "--coverage" 56 | LDFLAGS: "--coverage" 57 | run: cmake -DUSE_THIRDPARTY_LIBRARIES=OFF "-DCMAKE_TOOLCHAIN_FILE=${VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake" -GNinja -S ${{ github.workspace }} -B ${{ github.workspace }}/_build 58 | 59 | - name: Build 60 | run: cmake --build ${{ github.workspace }}/_build 61 | 62 | - name: Test 63 | run: ctest -V -LE Benchmark 64 | working-directory: "${{ github.workspace }}/_build" 65 | 66 | - name: Run lcov 67 | run: lcov --capture --directory "${{ github.workspace }}" --output-file coverage.info --no-external --exclude '*/tests/*' 68 | 69 | - name: Dump lcov 70 | run: lcov --list coverage.info 71 | 72 | - name: Coveralls 73 | uses: coverallsapp/github-action@v2 74 | with: 75 | github-token: ${{ secrets.GITHUB_TOKEN }} 76 | files: coverage.info 77 | -------------------------------------------------------------------------------- /.github/workflows/doxygen.yml: -------------------------------------------------------------------------------- 1 | name: Doxygen 2 | on: 3 | push: 4 | branches: 5 | - master 6 | 7 | jobs: 8 | build: 9 | name: Documentation 10 | runs-on: ubuntu-24.04 11 | steps: 12 | - name: Checkout source 13 | uses: actions/checkout@v4 14 | 15 | - name: Install doxygen 16 | run: | 17 | sudo apt-get remove -y --purge man-db # avoid time-consuming trigger 18 | sudo apt-get update 19 | sudo apt-get install -y doxygen graphviz 20 | 21 | - name: Generate doxygen 22 | run: doxygen 23 | working-directory: "${{ github.workspace }}/doc" 24 | 25 | - name: Deploy documentation 26 | uses: peaceiris/actions-gh-pages@v4 27 | with: 28 | github_token: ${{ secrets.GITHUB_TOKEN }} 29 | force_orphan: true 30 | publish_dir: ./doc/html 31 | -------------------------------------------------------------------------------- /.github/workflows/linting.yml: -------------------------------------------------------------------------------- 1 | name: Linting 2 | on: 3 | pull_request: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | iwyu: 10 | name: Include What You Use 11 | runs-on: ubuntu-latest 12 | container: 13 | image: debian:sid-slim 14 | steps: 15 | - name: Install dependencies 16 | run: | 17 | apt-get update 18 | apt-get install -y --no-install-recommends ca-certificates clang-19 cmake git iwyu libbenchmark-dev libcurl4-openssl-dev ninja-build zlib1g-dev 19 | 20 | - name: Checkout source 21 | uses: actions/checkout@v4 22 | with: 23 | submodules: true 24 | 25 | - name: "CMake Configure" 26 | run: cmake -GNinja -DRUN_IWYU=ON -DCMAKE_C_COMPILER=clang-19 -DCMAKE_CXX_COMPILER=clang++-19 -S ${GITHUB_WORKSPACE} -B ${GITHUB_WORKSPACE}/_build 27 | 28 | - name: Build 29 | run: cmake --build ${GITHUB_WORKSPACE}/_build 2>&1 | tee ${GITHUB_WORKSPACE}/output.txt 30 | 31 | - name: Check build output 32 | run: if egrep -q 'should (add|remove) these lines' ${GITHUB_WORKSPACE}/output.txt; then exit 1; fi 33 | 34 | #- name: "CMake Configure" 35 | # run: cmake -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -S ${GITHUB_WORKSPACE} -B ${GITHUB_WORKSPACE}/_build 36 | 37 | #- name: "Run IWYU" 38 | # 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 39 | 40 | format: 41 | name: Clang Format 42 | runs-on: ubuntu-24.04 43 | steps: 44 | - name: Checkout source 45 | uses: actions/checkout@v4 46 | 47 | # clang-format comes pre-installed 48 | # https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2404-Readme.md 49 | 50 | - name: Run clang-format 51 | 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-15 -style=file -i {} \; 52 | 53 | - name: Check for changes 54 | run: git diff --exit-code 55 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | on: 2 | release: 3 | types: [created] 4 | 5 | name: Handle Release 6 | 7 | jobs: 8 | build: 9 | name: Upload Release Asset 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout code 13 | uses: actions/checkout@v4 14 | with: 15 | persist-credentials: false 16 | submodules: true 17 | 18 | - name: Create tarball including submodules 19 | shell: bash 20 | env: 21 | PREFIX: prometheus-cpp-with-submodules 22 | run: | 23 | git archive --prefix "${PREFIX}/" -o "${PREFIX}.tar" HEAD 24 | git submodule foreach --recursive "git archive --prefix=${PREFIX}/\$path/ --output=\$sha1.tar HEAD && tar --concatenate --file=$(pwd)/${PREFIX}.tar \$sha1.tar && rm \$sha1.tar" 25 | gzip "${PREFIX}.tar" 26 | 27 | # using the official actions/upload-release-asset action would be preferred but is blocked by 28 | # https://github.com/actions/upload-release-asset/pull/41 29 | - name: Upload the artifacts 30 | uses: skx/github-action-publish-binaries@75ce5546020fc1848da842f40240f9fa03e7a3a8 # release-0.14 31 | env: 32 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 33 | with: 34 | args: prometheus-cpp-with-submodules.tar.gz 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bazel-* 2 | cmake-build-*/ 3 | _*/ 4 | .idea/ 5 | doc/html/ 6 | .vscode 7 | build 8 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "googletest"] 2 | path = 3rdparty/googletest 3 | url = https://github.com/google/googletest.git 4 | [submodule "civetweb"] 5 | path = 3rdparty/civetweb 6 | url = https://github.com/civetweb/civetweb.git 7 | -------------------------------------------------------------------------------- /BUILD.bazel: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016-2021 Jupp Mueller 4 | Copyright (c) 2017-2022 Gregor Jasny 5 | 6 | And many contributors, see 7 | https://github.com/jupp0r/prometheus-cpp/graphs/contributors 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in all 17 | copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | -------------------------------------------------------------------------------- /MODULE.bazel: -------------------------------------------------------------------------------- 1 | module( 2 | name = "prometheus-cpp", 3 | version = "1.3.0", 4 | repo_name = "com_github_jupp0r_prometheus_cpp", 5 | ) 6 | 7 | bazel_dep(name = "boringssl", version = "0.20250311.0") 8 | bazel_dep(name = "civetweb", version = "1.16.bcr.1") 9 | bazel_dep(name = "curl", version = "8.8.0.bcr.3") 10 | bazel_dep(name = "platforms", version = "0.0.11") 11 | bazel_dep(name = "rules_cc", version = "0.1.1") 12 | bazel_dep(name = "zlib", version = "1.3.1.bcr.5") 13 | 14 | bazel_dep(name = "google_benchmark", version = "1.9.1", dev_dependency = True) 15 | bazel_dep(name = "googletest", version = "1.16.0", dev_dependency = True) 16 | 17 | # due to 18 | # https://github.com/bazelbuild/bazel/issues/24426 19 | # https://github.com/bazelbuild/bazel-central-registry/pull/3320 20 | bazel_dep(name = "re2", version = "2024-07-02.bcr.1") 21 | -------------------------------------------------------------------------------- /WORKSPACE.bzlmod: -------------------------------------------------------------------------------- 1 | # When Bzlmod is enabled, this file replaces the content of the original WORKSPACE 2 | # and makes sure no WORKSPACE prefix or suffix are added when Bzlmod is enabled. 3 | -------------------------------------------------------------------------------- /bazel/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files( 2 | glob([ 3 | "*.tpl", 4 | ]), 5 | visibility = ["//visibility:public"], 6 | ) 7 | -------------------------------------------------------------------------------- /bazel/dummy_export.h.tpl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define {BASE_NAME}_EXPORT 4 | #define {BASE_NAME}_NO_EXPORT 5 | -------------------------------------------------------------------------------- /bazel/export_header.bzl: -------------------------------------------------------------------------------- 1 | def _generate_dummy_export_header_impl(ctx): 2 | ctx.actions.expand_template( 3 | template = ctx.file._template, 4 | output = ctx.outputs.header_file, 5 | substitutions = { 6 | "{BASE_NAME}": ctx.attr.basename, 7 | }, 8 | ) 9 | 10 | generate_dummy_export_header = rule( 11 | attrs = { 12 | "basename": attr.string(mandatory = True), 13 | "header": attr.string(mandatory = True), 14 | "_template": attr.label( 15 | allow_single_file = True, 16 | default = Label("@com_github_jupp0r_prometheus_cpp//bazel:dummy_export.h.tpl"), 17 | ), 18 | }, 19 | implementation = _generate_dummy_export_header_impl, 20 | outputs = {"header_file": "%{header}"}, 21 | ) 22 | -------------------------------------------------------------------------------- /cmake/CheckAtomic.cmake: -------------------------------------------------------------------------------- 1 | # Inspired by CheckAtomic.cmake from LLVM project: 2 | # https://github.com/llvm/llvm-project/blob/master/llvm/cmake/modules/CheckAtomic.cmake 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 5 | 6 | include(CheckCXXSourceCompiles) 7 | include(CheckLibraryExists) 8 | 9 | function(check_working_cxx_atomics varname) 10 | check_cxx_source_compiles(" 11 | #include 12 | #include 13 | std::atomic x(0); 14 | int main() { 15 | std::uint64_t i = x.load(std::memory_order_relaxed); 16 | return static_cast(i); 17 | } 18 | " ${varname}) 19 | endfunction() 20 | 21 | if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") 22 | # First check if atomics work without the library. 23 | check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB) 24 | # If not, check if the library exists, and atomics work with it. 25 | if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB) 26 | check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMIC) 27 | if(HAVE_CXX_LIBATOMIC) 28 | list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") 29 | check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB) 30 | if(NOT HAVE_CXX_ATOMICS_WITH_LIB) 31 | message(FATAL_ERROR "Host compiler must support 64-bit std::atomic!") 32 | endif() 33 | else() 34 | message(FATAL_ERROR "Host compiler appears to require libatomic for 64-bit operations, but cannot find it.") 35 | endif() 36 | endif() 37 | endif() 38 | -------------------------------------------------------------------------------- /cmake/FindTelegraf.cmake: -------------------------------------------------------------------------------- 1 | find_program(Telegraf_EXECUTABLE NAMES telegraf) 2 | mark_as_advanced(Telegraf_EXECUTABLE) 3 | 4 | include(FindPackageHandleStandardArgs) 5 | find_package_handle_standard_args(Telegraf 6 | FOUND_VAR Telegraf_FOUND 7 | REQUIRED_VARS 8 | Telegraf_EXECUTABLE 9 | ) 10 | -------------------------------------------------------------------------------- /cmake/civetweb-3rdparty-config.cmake: -------------------------------------------------------------------------------- 1 | get_filename_component(_IMPORT_PREFIX "${PROJECT_SOURCE_DIR}/3rdparty/civetweb/" ABSOLUTE) 2 | 3 | macro(set_and_check _var _file) 4 | set(${_var} "${_file}") 5 | if(NOT EXISTS "${_file}") 6 | message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !") 7 | endif() 8 | endmacro() 9 | 10 | set_and_check(CIVETWEB_INCLUDE_DIR ${_IMPORT_PREFIX}/include) 11 | set(CIVETWEB_INCLUDE_DIRS "${CIVETWEB_INCLUDE_DIR}") 12 | 13 | add_library(civetweb OBJECT 14 | ${_IMPORT_PREFIX}/include/CivetServer.h 15 | ${_IMPORT_PREFIX}/include/civetweb.h 16 | ${_IMPORT_PREFIX}/src/CivetServer.cpp 17 | ${_IMPORT_PREFIX}/src/civetweb.c 18 | ${_IMPORT_PREFIX}/src/handle_form.inl 19 | ${_IMPORT_PREFIX}/src/md5.inl 20 | ) 21 | 22 | set_property(TARGET civetweb PROPERTY PUBLIC_HEADER 23 | ${_IMPORT_PREFIX}/include/CivetServer.h 24 | ${_IMPORT_PREFIX}/include/civetweb.h 25 | ) 26 | 27 | target_compile_definitions(civetweb 28 | PRIVATE 29 | CIVETWEB_API= 30 | USE_IPV6 31 | NDEBUG 32 | NO_CGI 33 | NO_CACHING 34 | NO_FILES 35 | SOCKET_TIMEOUT_QUANTUM=200 36 | ) 37 | 38 | target_compile_options(civetweb 39 | PRIVATE 40 | $<$:-w> 41 | $<$:-w> 42 | ) 43 | 44 | target_include_directories(civetweb 45 | PRIVATE 46 | ${CIVETWEB_INCLUDE_DIRS} 47 | ) 48 | 49 | if(THIRDPARTY_CIVETWEB_WITH_SSL) 50 | include(CMakeFindDependencyMacro) 51 | find_dependency(OpenSSL) 52 | if(OPENSSL_VERSION VERSION_GREATER_EQUAL 1.1) 53 | target_compile_definitions(civetweb PRIVATE OPENSSL_API_1_1) 54 | endif() 55 | target_compile_definitions(civetweb PRIVATE NO_SSL_DL) 56 | target_link_libraries(civetweb PUBLIC OpenSSL::SSL) 57 | else() 58 | target_compile_definitions(civetweb PRIVATE NO_SSL) 59 | endif() 60 | 61 | if(BUILD_SHARED_LIBS) 62 | set_target_properties(civetweb PROPERTIES 63 | POSITION_INDEPENDENT_CODE ON 64 | C_VISIBILITY_PRESET hidden 65 | CXX_VISIBILITY_PRESET hidden 66 | VISIBILITY_INLINES_HIDDEN ON 67 | ) 68 | endif() 69 | 70 | set_target_properties(civetweb PROPERTIES 71 | C_INCLUDE_WHAT_YOU_USE "" 72 | CXX_INCLUDE_WHAT_YOU_USE "" 73 | ) 74 | -------------------------------------------------------------------------------- /cmake/googlemock-3rdparty-config.cmake: -------------------------------------------------------------------------------- 1 | get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_DIR}/../3rdparty/googletest/" ABSOLUTE) 2 | 3 | find_package(Threads QUIET) 4 | 5 | add_library(gmock_main STATIC EXCLUDE_FROM_ALL 6 | ${_IMPORT_PREFIX}/googletest/src/gtest-all.cc 7 | ${_IMPORT_PREFIX}/googlemock/src/gmock-all.cc 8 | ${_IMPORT_PREFIX}/googlemock/src/gmock_main.cc 9 | ) 10 | 11 | target_include_directories(gmock_main SYSTEM 12 | PUBLIC 13 | ${_IMPORT_PREFIX}/googletest/include 14 | ${_IMPORT_PREFIX}/googlemock/include 15 | PRIVATE 16 | ${_IMPORT_PREFIX}/googletest 17 | ${_IMPORT_PREFIX}/googlemock 18 | ) 19 | 20 | target_link_libraries(gmock_main 21 | PRIVATE 22 | Threads::Threads 23 | ) 24 | add_library(GTest::gmock_main ALIAS gmock_main) 25 | 26 | set_target_properties(gmock_main PROPERTIES 27 | C_INCLUDE_WHAT_YOU_USE "" 28 | CXX_INCLUDE_WHAT_YOU_USE "" 29 | ) 30 | -------------------------------------------------------------------------------- /cmake/googletest.imp: -------------------------------------------------------------------------------- 1 | [ 2 | { include: [ "@", private, "", public ] }, 3 | { include: [ "@", private, "", public ] }, 4 | { include: [ "@", private, "", public ]}, 5 | { include: [ "@", private, "", public ]} 6 | ] 7 | -------------------------------------------------------------------------------- /cmake/project-import-cmake/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12 FATAL_ERROR) 2 | 3 | project(prometheus-cpp-import) 4 | 5 | find_package(prometheus-cpp CONFIG REQUIRED) 6 | 7 | if(NOT DEFINED prometheus-cpp_VERSION) 8 | message(FATAL_ERROR "prometheus-cpp_VERSION is not defined") 9 | endif() 10 | 11 | if(PROMETHEUS_CPP_ENABLE_PUSH) 12 | add_executable(sample-client sample_client.cc) 13 | target_link_libraries(sample-client PRIVATE prometheus-cpp::push $<$:Ws2_32>) 14 | endif() 15 | 16 | if(PROMETHEUS_CPP_ENABLE_PULL) 17 | add_executable(sample-server sample_server.cc) 18 | target_link_libraries(sample-server PRIVATE prometheus-cpp::pull) 19 | endif() 20 | -------------------------------------------------------------------------------- /cmake/project-import-cmake/sample_client.cc: -------------------------------------------------------------------------------- 1 | ../../push/tests/integration/sample_client.cc -------------------------------------------------------------------------------- /cmake/project-import-cmake/sample_server.cc: -------------------------------------------------------------------------------- 1 | ../../pull/tests/integration/sample_server.cc -------------------------------------------------------------------------------- /cmake/project-import-pkgconfig/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12 FATAL_ERROR) 2 | 3 | project(prometheus-cpp-import) 4 | 5 | set(CMAKE_CXX_STANDARD 11) 6 | 7 | find_package(PkgConfig REQUIRED) 8 | 9 | pkg_check_modules(PROMETHEUS_CPP_CORE REQUIRED prometheus-cpp-core) 10 | pkg_check_modules(PROMETHEUS_CPP_PUSH IMPORTED_TARGET prometheus-cpp-push) 11 | pkg_check_modules(PROMETHEUS_CPP_PULL IMPORTED_TARGET prometheus-cpp-pull) 12 | 13 | if(PROMETHEUS_CPP_PUSH_FOUND) 14 | add_executable(sample-client sample_client.cc) 15 | target_link_libraries(sample-client PRIVATE PkgConfig::PROMETHEUS_CPP_PUSH $<$:Ws2_32>) 16 | endif() 17 | 18 | if(PROMETHEUS_CPP_PULL_FOUND) 19 | add_executable(sample-server sample_server.cc) 20 | target_link_libraries(sample-server PRIVATE PkgConfig::PROMETHEUS_CPP_PULL) 21 | endif() 22 | -------------------------------------------------------------------------------- /cmake/project-import-pkgconfig/sample_client.cc: -------------------------------------------------------------------------------- 1 | ../../push/tests/integration/sample_client.cc -------------------------------------------------------------------------------- /cmake/project-import-pkgconfig/sample_server.cc: -------------------------------------------------------------------------------- 1 | ../../pull/tests/integration/sample_server.cc -------------------------------------------------------------------------------- /cmake/prometheus-cpp-config.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | include(CMakeFindDependencyMacro) 3 | 4 | set_and_check(prometheus-cpp_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@") 5 | 6 | set(PROMETHEUS_CPP_ENABLE_PULL @ENABLE_PULL@) 7 | set(PROMETHEUS_CPP_ENABLE_PUSH @ENABLE_PUSH@) 8 | set(PROMETHEUS_CPP_USE_COMPRESSION @ENABLE_COMPRESSION@) 9 | set(PROMETHEUS_CPP_USE_THIRDPARTY_LIBRARIES @USE_THIRDPARTY_LIBRARIES@) 10 | set(PROMETHEUS_CPP_THIRDPARTY_CIVETWEB_WITH_SSL @THIRDPARTY_CIVETWEB_WITH_SSL@) 11 | 12 | set(CMAKE_THREAD_PREFER_PTHREAD TRUE) 13 | find_dependency(Threads) 14 | unset(CMAKE_THREAD_PREFER_PTHREAD) 15 | 16 | if(PROMETHEUS_CPP_ENABLE_PULL) 17 | if(PROMETHEUS_CPP_USE_THIRDPARTY_LIBRARIES) 18 | if(PROMETHEUS_CPP_THIRDPARTY_CIVETWEB_WITH_SSL) 19 | find_dependency(OpenSSL) 20 | endif() 21 | else() 22 | find_dependency(civetweb) 23 | endif() 24 | endif() 25 | 26 | if(PROMETHEUS_CPP_ENABLE_PULL AND PROMETHEUS_CPP_USE_COMPRESSION) 27 | find_dependency(ZLIB) 28 | endif() 29 | 30 | if(PROMETHEUS_CPP_ENABLE_PUSH) 31 | find_dependency(CURL) 32 | endif() 33 | 34 | include("${CMAKE_CURRENT_LIST_DIR}/prometheus-cpp-targets.cmake") 35 | -------------------------------------------------------------------------------- /cmake/prometheus-cpp-core.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | exec_prefix=${prefix} 3 | includedir=@PROMETHEUS_CPP_PKGCONFIG_INCLUDEDIR@ 4 | libdir=@PROMETHEUS_CPP_PKGCONFIG_LIBDIR@ 5 | 6 | Name: @PROJECT_NAME@-core 7 | Description: @PROJECT_DESCRIPTION@ 8 | URL: @PROJECT_HOMEPAGE_URL@ 9 | Version: @PROJECT_VERSION@ 10 | Requires: 11 | Requires.private: @PKGCONFIG_REQUIRES@ 12 | Cflags: -I${includedir} 13 | Libs: -L${libdir} -l@PROJECT_NAME@-core 14 | Libs.private: @CMAKE_THREAD_LIBS_INIT@ @PKGCONFIG_LIBS@ -------------------------------------------------------------------------------- /cmake/prometheus-cpp-pull.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | exec_prefix=${prefix} 3 | includedir=@PROMETHEUS_CPP_PKGCONFIG_INCLUDEDIR@ 4 | libdir=@PROMETHEUS_CPP_PKGCONFIG_LIBDIR@ 5 | 6 | Name: @PROJECT_NAME@-pull 7 | Description: @PROJECT_DESCRIPTION@ 8 | URL: @PROJECT_HOMEPAGE_URL@ 9 | Version: @PROJECT_VERSION@ 10 | Requires: @PROJECT_NAME@-core 11 | Requires.private: @PKGCONFIG_REQUIRES@ 12 | Cflags: -I${includedir} 13 | Libs: -L${libdir} -l@PROJECT_NAME@-pull 14 | Libs.private: @CMAKE_THREAD_LIBS_INIT@ @PKGCONFIG_LIBS@ 15 | -------------------------------------------------------------------------------- /cmake/prometheus-cpp-push.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | exec_prefix=${prefix} 3 | includedir=@PROMETHEUS_CPP_PKGCONFIG_INCLUDEDIR@ 4 | libdir=@PROMETHEUS_CPP_PKGCONFIG_LIBDIR@ 5 | 6 | Name: @PROJECT_NAME@-push 7 | Description: @PROJECT_DESCRIPTION@ 8 | URL: @PROJECT_HOMEPAGE_URL@ 9 | Version: @PROJECT_VERSION@ 10 | Requires: @PROJECT_NAME@-core @PKGCONFIG_REQUIRES@ 11 | Requires.private: 12 | Cflags: -I${includedir} 13 | Libs: -L${libdir} -l@PROJECT_NAME@-push 14 | Libs.private: @CMAKE_THREAD_LIBS_INIT@ @PKGCONFIG_LIBS@ 15 | -------------------------------------------------------------------------------- /core/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("//bazel:export_header.bzl", "generate_dummy_export_header") 2 | 3 | generate_dummy_export_header( 4 | name = "export_header", 5 | basename = "PROMETHEUS_CPP_CORE", 6 | header = "include/prometheus/detail/core_export.h", 7 | ) 8 | 9 | cc_library( 10 | name = "core", 11 | srcs = glob([ 12 | "src/**/*.cc", 13 | "src/**/*.h", 14 | ]), 15 | hdrs = glob( 16 | ["include/**/*.h"], 17 | ) + [":export_header"], 18 | strip_include_prefix = "include", 19 | visibility = ["//visibility:public"], 20 | ) 21 | -------------------------------------------------------------------------------- /core/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(core 3 | src/check_names.cc 4 | src/counter.cc 5 | src/detail/builder.cc 6 | src/detail/ckms_quantiles.cc 7 | src/detail/time_window_quantiles.cc 8 | src/detail/utils.cc 9 | src/family.cc 10 | src/gauge.cc 11 | src/histogram.cc 12 | src/info.cc 13 | src/registry.cc 14 | src/serializer.cc 15 | src/summary.cc 16 | src/text_serializer.cc 17 | ) 18 | 19 | add_library(${PROJECT_NAME}::core ALIAS core) 20 | 21 | target_compile_features(core 22 | PUBLIC 23 | cxx_std_11 24 | ) 25 | 26 | target_link_libraries(core 27 | PRIVATE 28 | Threads::Threads 29 | $<$,$>>:rt> 30 | ) 31 | 32 | if(HAVE_CXX_LIBATOMIC) 33 | # the exported library config must use libatomic unconditionally 34 | # (the HAVE_CXX_LIBATOMIC variable should not leak into the target config) 35 | target_link_libraries(core PUBLIC atomic) 36 | endif() 37 | 38 | target_include_directories(core 39 | PUBLIC 40 | $ 41 | $ 42 | ) 43 | 44 | set_target_properties(core 45 | PROPERTIES 46 | OUTPUT_NAME ${PROJECT_NAME}-core 47 | DEFINE_SYMBOL PROMETHEUS_CPP_CORE_EXPORTS 48 | VERSION "${PROJECT_VERSION}" 49 | SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}" 50 | ) 51 | 52 | generate_export_header(core 53 | BASE_NAME ${PROJECT_NAME}-core 54 | EXPORT_FILE_NAME include/prometheus/detail/core_export.h 55 | ) 56 | 57 | install( 58 | TARGETS core 59 | EXPORT ${PROJECT_NAME}-targets 60 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 61 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 62 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 63 | INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} 64 | ) 65 | 66 | install( 67 | DIRECTORY include/ ${CMAKE_CURRENT_BINARY_DIR}/include/ 68 | DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} 69 | ) 70 | 71 | if(GENERATE_PKGCONFIG) 72 | set(PKGCONFIG_LIBS) 73 | set(PKGCONFIG_REQUIRES) 74 | 75 | if(HAVE_CXX_LIBATOMIC) 76 | string(APPEND PKGCONFIG_LIBS " -latomic") 77 | endif() 78 | 79 | configure_file( 80 | ${PROJECT_SOURCE_DIR}/cmake/prometheus-cpp-core.pc.in 81 | ${CMAKE_CURRENT_BINARY_DIR}/prometheus-cpp-core.pc 82 | @ONLY 83 | ) 84 | 85 | install( 86 | FILES ${CMAKE_CURRENT_BINARY_DIR}/prometheus-cpp-core.pc 87 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig 88 | ) 89 | 90 | unset(PKGCONFIG_LIBS) 91 | unset(PKGCONFIG_REQUIRES) 92 | endif() 93 | 94 | if(ENABLE_TESTING) 95 | add_subdirectory(tests) 96 | 97 | if(benchmark_FOUND) 98 | add_subdirectory(benchmarks) 99 | endif() 100 | endif() 101 | -------------------------------------------------------------------------------- /core/benchmarks/BUILD.bazel: -------------------------------------------------------------------------------- 1 | cc_binary( 2 | name = "benchmarks", 3 | srcs = glob([ 4 | "*.cc", 5 | "*.h", 6 | ]), 7 | linkstatic = True, 8 | deps = [ 9 | "//core", 10 | "@google_benchmark//:benchmark", 11 | ], 12 | ) 13 | -------------------------------------------------------------------------------- /core/benchmarks/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(benchmarks 3 | main.cc 4 | benchmark_helpers.cc 5 | benchmark_helpers.h 6 | counter_bench.cc 7 | gauge_bench.cc 8 | histogram_bench.cc 9 | info_bench.cc 10 | registry_bench.cc 11 | summary_bench.cc 12 | ) 13 | 14 | target_link_libraries(benchmarks 15 | PRIVATE 16 | ${PROJECT_NAME}::core 17 | benchmark::benchmark 18 | ) 19 | 20 | add_test( 21 | NAME benchmarks 22 | COMMAND benchmarks 23 | ) 24 | 25 | set_property( 26 | TEST benchmarks 27 | APPEND PROPERTY LABELS Benchmark 28 | ) 29 | -------------------------------------------------------------------------------- /core/benchmarks/benchmark_helpers.cc: -------------------------------------------------------------------------------- 1 | #include "benchmark_helpers.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | std::string GenerateRandomString(std::size_t length) { 8 | auto randchar = []() -> char { 9 | const char charset[] = "abcdefghijklmnopqrstuvwxyz"; 10 | const std::size_t max_index = (sizeof(charset) - 1); 11 | return charset[rand() % max_index]; 12 | }; 13 | std::string str(length, 0); 14 | std::generate_n(str.begin(), length, randchar); 15 | return str; 16 | } 17 | 18 | prometheus::Labels GenerateRandomLabels(std::size_t number_of_pairs) { 19 | const auto label_character_count = 10; 20 | auto label_pairs = prometheus::Labels{}; 21 | for (std::size_t i = 0; i < number_of_pairs; i++) { 22 | label_pairs.insert({GenerateRandomString(label_character_count), 23 | GenerateRandomString(label_character_count)}); 24 | } 25 | return label_pairs; 26 | } 27 | -------------------------------------------------------------------------------- /core/benchmarks/benchmark_helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "prometheus/labels.h" 7 | 8 | std::string GenerateRandomString(std::size_t length); 9 | prometheus::Labels GenerateRandomLabels(std::size_t number_of_labels); 10 | -------------------------------------------------------------------------------- /core/benchmarks/counter_bench.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "prometheus/counter.h" 4 | #include "prometheus/family.h" 5 | #include "prometheus/registry.h" 6 | 7 | static void BM_Counter_Increment(benchmark::State& state) { 8 | using prometheus::BuildCounter; 9 | using prometheus::Counter; 10 | using prometheus::Registry; 11 | Registry registry; 12 | auto& counter_family = 13 | BuildCounter().Name("benchmark_counter").Help("").Register(registry); 14 | auto& counter = counter_family.Add({}); 15 | 16 | while (state.KeepRunning()) counter.Increment(); 17 | } 18 | BENCHMARK(BM_Counter_Increment); 19 | 20 | static void BM_Counter_Collect(benchmark::State& state) { 21 | using prometheus::BuildCounter; 22 | using prometheus::Counter; 23 | using prometheus::Registry; 24 | Registry registry; 25 | auto& counter_family = 26 | BuildCounter().Name("benchmark_counter").Help("").Register(registry); 27 | auto& counter = counter_family.Add({}); 28 | 29 | while (state.KeepRunning()) { 30 | benchmark::DoNotOptimize(counter.Collect()); 31 | }; 32 | } 33 | BENCHMARK(BM_Counter_Collect); 34 | -------------------------------------------------------------------------------- /core/benchmarks/gauge_bench.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "prometheus/family.h" 4 | #include "prometheus/gauge.h" 5 | #include "prometheus/registry.h" 6 | 7 | static void BM_Gauge_Increment(benchmark::State& state) { 8 | using prometheus::BuildGauge; 9 | using prometheus::Gauge; 10 | using prometheus::Registry; 11 | Registry registry; 12 | auto& gauge_family = 13 | BuildGauge().Name("benchmark_gauge").Help("").Register(registry); 14 | auto& gauge = gauge_family.Add({}); 15 | 16 | while (state.KeepRunning()) gauge.Increment(2); 17 | } 18 | BENCHMARK(BM_Gauge_Increment); 19 | 20 | static void BM_Gauge_Decrement(benchmark::State& state) { 21 | using prometheus::BuildGauge; 22 | using prometheus::Gauge; 23 | using prometheus::Registry; 24 | Registry registry; 25 | auto& gauge_family = 26 | BuildGauge().Name("benchmark_gauge").Help("").Register(registry); 27 | auto& gauge = gauge_family.Add({}); 28 | 29 | while (state.KeepRunning()) gauge.Decrement(2); 30 | } 31 | BENCHMARK(BM_Gauge_Decrement); 32 | 33 | static void BM_Gauge_SetToCurrentTime(benchmark::State& state) { 34 | using prometheus::BuildGauge; 35 | using prometheus::Gauge; 36 | using prometheus::Registry; 37 | Registry registry; 38 | auto& gauge_family = 39 | BuildGauge().Name("benchmark_gauge").Help("").Register(registry); 40 | auto& gauge = gauge_family.Add({}); 41 | 42 | while (state.KeepRunning()) gauge.SetToCurrentTime(); 43 | } 44 | BENCHMARK(BM_Gauge_SetToCurrentTime); 45 | 46 | static void BM_Gauge_Collect(benchmark::State& state) { 47 | using prometheus::BuildGauge; 48 | using prometheus::Gauge; 49 | using prometheus::Registry; 50 | Registry registry; 51 | auto& gauge_family = 52 | BuildGauge().Name("benchmark_gauge").Help("").Register(registry); 53 | auto& gauge = gauge_family.Add({}); 54 | 55 | while (state.KeepRunning()) { 56 | benchmark::DoNotOptimize(gauge.Collect()); 57 | }; 58 | } 59 | BENCHMARK(BM_Gauge_Collect); 60 | -------------------------------------------------------------------------------- /core/benchmarks/histogram_bench.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "prometheus/family.h" 9 | #include "prometheus/histogram.h" 10 | #include "prometheus/registry.h" 11 | 12 | using prometheus::Histogram; 13 | 14 | static Histogram::BucketBoundaries CreateLinearBuckets(std::int64_t start, 15 | std::int64_t end, 16 | std::int64_t step) { 17 | auto bucket_boundaries = Histogram::BucketBoundaries{}; 18 | for (auto i = start; i < end; i += step) { 19 | bucket_boundaries.push_back(i); 20 | } 21 | return bucket_boundaries; 22 | } 23 | 24 | static void BM_Histogram_Observe(benchmark::State& state) { 25 | using prometheus::BuildHistogram; 26 | using prometheus::Histogram; 27 | using prometheus::Registry; 28 | 29 | const auto number_of_buckets = state.range(0); 30 | 31 | Registry registry; 32 | auto& histogram_family = 33 | BuildHistogram().Name("benchmark_histogram").Help("").Register(registry); 34 | auto bucket_boundaries = CreateLinearBuckets(0, number_of_buckets - 1, 1); 35 | auto& histogram = histogram_family.Add({}, bucket_boundaries); 36 | std::random_device rd; 37 | std::mt19937 gen(rd()); 38 | std::uniform_real_distribution<> d(0, number_of_buckets); 39 | 40 | while (state.KeepRunning()) { 41 | auto observation = d(gen); 42 | auto start = std::chrono::high_resolution_clock::now(); 43 | histogram.Observe(observation); 44 | auto end = std::chrono::high_resolution_clock::now(); 45 | 46 | auto elapsed_seconds = 47 | std::chrono::duration_cast>(end - start); 48 | state.SetIterationTime(elapsed_seconds.count()); 49 | } 50 | } 51 | BENCHMARK(BM_Histogram_Observe)->Range(0, 4096)->UseManualTime(); 52 | 53 | static void BM_Histogram_Collect(benchmark::State& state) { 54 | using prometheus::BuildHistogram; 55 | using prometheus::Histogram; 56 | using prometheus::Registry; 57 | 58 | const auto number_of_buckets = state.range(0); 59 | 60 | Registry registry; 61 | auto& histogram_family = 62 | BuildHistogram().Name("benchmark_histogram").Help("").Register(registry); 63 | auto bucket_boundaries = CreateLinearBuckets(0, number_of_buckets - 1, 1); 64 | auto& histogram = histogram_family.Add({}, bucket_boundaries); 65 | 66 | while (state.KeepRunning()) { 67 | benchmark::DoNotOptimize(histogram.Collect()); 68 | } 69 | } 70 | BENCHMARK(BM_Histogram_Collect)->Range(0, 4096); 71 | -------------------------------------------------------------------------------- /core/benchmarks/info_bench.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "prometheus/family.h" 4 | #include "prometheus/info.h" 5 | #include "prometheus/registry.h" 6 | 7 | static void BM_Info_Collect(benchmark::State& state) { 8 | using prometheus::BuildInfo; 9 | using prometheus::Info; 10 | using prometheus::Registry; 11 | Registry registry; 12 | auto& info_family = 13 | BuildInfo().Name("benchmark_info").Help("").Register(registry); 14 | auto& info = info_family.Add({}); 15 | 16 | while (state.KeepRunning()) { 17 | benchmark::DoNotOptimize(info.Collect()); 18 | }; 19 | } 20 | BENCHMARK(BM_Info_Collect); 21 | -------------------------------------------------------------------------------- /core/benchmarks/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | BENCHMARK_MAIN(); 4 | -------------------------------------------------------------------------------- /core/benchmarks/registry_bench.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "benchmark_helpers.h" 6 | #include "prometheus/counter.h" 7 | #include "prometheus/family.h" 8 | #include "prometheus/registry.h" 9 | 10 | static void BM_Registry_CreateFamily(benchmark::State& state) { 11 | using prometheus::BuildCounter; 12 | using prometheus::Counter; 13 | using prometheus::Registry; 14 | Registry registry; 15 | 16 | while (state.KeepRunning()) 17 | BuildCounter().Name("benchmark_counter").Help("").Register(registry); 18 | } 19 | BENCHMARK(BM_Registry_CreateFamily); 20 | 21 | static void BM_Registry_CreateCounter(benchmark::State& state) { 22 | using prometheus::BuildCounter; 23 | using prometheus::Counter; 24 | using prometheus::Registry; 25 | Registry registry; 26 | auto& counter_family = BuildCounter() 27 | .Labels(GenerateRandomLabels(10)) 28 | .Name("benchmark_counter") 29 | .Help("") 30 | .Register(registry); 31 | 32 | while (state.KeepRunning()) { 33 | auto labels = GenerateRandomLabels(state.range(0)); 34 | 35 | auto start = std::chrono::high_resolution_clock::now(); 36 | counter_family.Add(labels); 37 | auto end = std::chrono::high_resolution_clock::now(); 38 | 39 | auto elapsed_seconds = 40 | std::chrono::duration_cast>(end - start); 41 | state.SetIterationTime(elapsed_seconds.count()); 42 | } 43 | } 44 | BENCHMARK(BM_Registry_CreateCounter)->Range(0, 4096); 45 | -------------------------------------------------------------------------------- /core/benchmarks/summary_bench.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "prometheus/family.h" 10 | #include "prometheus/registry.h" 11 | #include "prometheus/summary.h" 12 | 13 | using prometheus::Summary; 14 | 15 | static const auto ITERATIONS = 262144; 16 | 17 | static Summary::Quantiles CreateLinearQuantiles(int count) { 18 | static auto generator = [](double x) { 19 | static auto exp = [](double x) { 20 | static const double A = 2; 21 | return 1 - std::exp(-A * x); 22 | }; 23 | 24 | return exp(x) / exp(1); 25 | }; 26 | 27 | auto quantiles = Summary::Quantiles{}; 28 | for (auto i = 0; i < count; ++i) { 29 | quantiles.emplace_back(generator(double(i) / count), 0.01); 30 | } 31 | return quantiles; 32 | } 33 | 34 | static void BM_Summary_Observe(benchmark::State& state) { 35 | using prometheus::BuildSummary; 36 | using prometheus::Registry; 37 | using prometheus::Summary; 38 | 39 | const auto number_of_quantiles = state.range(0); 40 | 41 | Registry registry; 42 | auto& summary_family = 43 | BuildSummary().Name("benchmark_summary").Help("").Register(registry); 44 | auto quantiles = CreateLinearQuantiles(number_of_quantiles); 45 | auto& summary = summary_family.Add({}, quantiles); 46 | std::random_device rd; 47 | std::mt19937 gen(rd()); 48 | std::uniform_real_distribution<> d(0, 100); 49 | 50 | while (state.KeepRunning()) { 51 | auto observation = d(gen); 52 | auto start = std::chrono::high_resolution_clock::now(); 53 | summary.Observe(observation); 54 | auto end = std::chrono::high_resolution_clock::now(); 55 | 56 | auto elapsed_seconds = 57 | std::chrono::duration_cast>(end - start); 58 | state.SetIterationTime(elapsed_seconds.count()); 59 | } 60 | } 61 | BENCHMARK(BM_Summary_Observe)->Range(0, 64)->Iterations(ITERATIONS); 62 | 63 | static void BM_Summary_Collect(benchmark::State& state) { 64 | using prometheus::BuildSummary; 65 | using prometheus::Registry; 66 | using prometheus::Summary; 67 | 68 | const auto number_of_quantiles = state.range(0); 69 | const auto number_of_entries = state.range(1); 70 | 71 | Registry registry; 72 | auto& summary_family = 73 | BuildSummary().Name("benchmark_summary").Help("").Register(registry); 74 | auto quantiles = CreateLinearQuantiles(number_of_quantiles); 75 | auto& summary = summary_family.Add({}, quantiles); 76 | 77 | std::random_device rd; 78 | std::mt19937 gen(rd()); 79 | std::uniform_real_distribution<> d(0, 100); 80 | for (auto i = 1; i <= number_of_entries; ++i) summary.Observe(d(gen)); 81 | 82 | while (state.KeepRunning()) { 83 | benchmark::DoNotOptimize(summary.Collect()); 84 | } 85 | } 86 | BENCHMARK(BM_Summary_Collect)->RangePair(0, 64, 0, ITERATIONS); 87 | 88 | static void BM_Summary_Observe_Common(benchmark::State& state) { 89 | using prometheus::BuildSummary; 90 | using prometheus::Registry; 91 | using prometheus::Summary; 92 | 93 | Registry registry; 94 | auto& summary_family = 95 | BuildSummary().Name("benchmark_summary").Help("").Register(registry); 96 | auto& summary = summary_family.Add( 97 | {}, Summary::Quantiles{ 98 | {0.5, 0.05}, {0.9, 0.01}, {0.95, 0.005}, {0.99, 0.001}}); 99 | std::random_device rd; 100 | std::mt19937 gen(rd()); 101 | std::uniform_real_distribution<> d(0, 100); 102 | 103 | while (state.KeepRunning()) { 104 | auto observation = d(gen); 105 | auto start = std::chrono::high_resolution_clock::now(); 106 | summary.Observe(observation); 107 | auto end = std::chrono::high_resolution_clock::now(); 108 | 109 | auto elapsed_seconds = 110 | std::chrono::duration_cast>(end - start); 111 | state.SetIterationTime(elapsed_seconds.count()); 112 | } 113 | } 114 | BENCHMARK(BM_Summary_Observe_Common)->Iterations(ITERATIONS); 115 | 116 | static void BM_Summary_Collect_Common(benchmark::State& state) { 117 | using prometheus::BuildSummary; 118 | using prometheus::Registry; 119 | using prometheus::Summary; 120 | 121 | const auto number_of_entries = state.range(0); 122 | 123 | Registry registry; 124 | auto& summary_family = 125 | BuildSummary().Name("benchmark_summary").Help("").Register(registry); 126 | auto& summary = summary_family.Add( 127 | {}, Summary::Quantiles{ 128 | {0.5, 0.05}, {0.9, 0.01}, {0.95, 0.005}, {0.99, 0.001}}); 129 | 130 | std::random_device rd; 131 | std::mt19937 gen(rd()); 132 | std::uniform_real_distribution<> d(0, 100); 133 | for (auto i = 1; i <= number_of_entries; ++i) summary.Observe(d(gen)); 134 | 135 | while (state.KeepRunning()) { 136 | benchmark::DoNotOptimize(summary.Collect()); 137 | } 138 | } 139 | BENCHMARK(BM_Summary_Collect_Common)->Range(0, ITERATIONS); 140 | -------------------------------------------------------------------------------- /core/include/prometheus/check_names.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "prometheus/detail/core_export.h" 6 | #include "prometheus/metric_type.h" 7 | 8 | namespace prometheus { 9 | 10 | PROMETHEUS_CPP_CORE_EXPORT bool CheckMetricName(const std::string& name); 11 | PROMETHEUS_CPP_CORE_EXPORT bool CheckLabelName(const std::string& name, 12 | MetricType type); 13 | } // namespace prometheus 14 | -------------------------------------------------------------------------------- /core/include/prometheus/client_metric.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "prometheus/detail/core_export.h" 9 | 10 | namespace prometheus { 11 | 12 | struct PROMETHEUS_CPP_CORE_EXPORT ClientMetric { 13 | // Label 14 | 15 | struct Label { 16 | std::string name; 17 | std::string value; 18 | 19 | friend bool operator<(const Label& lhs, const Label& rhs) { 20 | return std::tie(lhs.name, lhs.value) < std::tie(rhs.name, rhs.value); 21 | } 22 | 23 | friend bool operator==(const Label& lhs, const Label& rhs) { 24 | return std::tie(lhs.name, lhs.value) == std::tie(rhs.name, rhs.value); 25 | } 26 | }; 27 | std::vector