Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| efd3086af2 | |||
| 30f69ec758 | |||
| c673e984b0 | |||
| 26b8e59066 | |||
| b8b0e75513 | |||
| 472ccc3929 | |||
| b16ed1de3b | |||
| 167f9216be | |||
| 1a9de428cb | |||
| eaeaf4ab3d | |||
| cf24fe9cbf | |||
| d351840a70 | |||
| 78c6c77c00 | |||
| 46582601ea | |||
| cdb4156702 | |||
| 642653a37f |
@@ -7,10 +7,13 @@ RUN apt-get update && apt-get upgrade -y && \
|
||||
g++-8 \
|
||||
git \
|
||||
jq \
|
||||
libcurl4-openssl-dev \
|
||||
libgmp-dev \
|
||||
libssl-dev \
|
||||
libusb-1.0-0-dev \
|
||||
llvm-7-dev \
|
||||
ninja-build \
|
||||
pkg-config \
|
||||
python3 \
|
||||
software-properties-common \
|
||||
zlib1g-dev \
|
||||
|
||||
@@ -7,8 +7,11 @@ RUN apt-get update && apt-get upgrade -y && \
|
||||
git \
|
||||
jq \
|
||||
libboost-all-dev \
|
||||
libcurl4-openssl-dev \
|
||||
libgmp-dev \
|
||||
libssl-dev \
|
||||
libusb-1.0-0-dev \
|
||||
llvm-11-dev \
|
||||
ninja-build \
|
||||
pkg-config \
|
||||
zstd
|
||||
|
||||
@@ -7,8 +7,11 @@ RUN apt-get update && apt-get upgrade -y && \
|
||||
git \
|
||||
jq \
|
||||
libboost-all-dev \
|
||||
libcurl4-openssl-dev \
|
||||
libgmp-dev \
|
||||
libssl-dev \
|
||||
libusb-1.0-0-dev \
|
||||
llvm-11-dev \
|
||||
ninja-build \
|
||||
pkg-config \
|
||||
zstd
|
||||
|
||||
@@ -12,7 +12,6 @@ jobs:
|
||||
label: triage
|
||||
org-project: 'Team Backlog'
|
||||
project-field: Status=Todo
|
||||
skip-if-existing-project: true
|
||||
secrets:
|
||||
token: ${{secrets.ENFCIBOT_REPO_AND_PROJECTS}}
|
||||
|
||||
|
||||
@@ -79,8 +79,6 @@ Testing/*
|
||||
build.tar.gz
|
||||
build/*
|
||||
build-debug/*
|
||||
deps/*
|
||||
dependencies/*
|
||||
|
||||
etc/eosio/node_*
|
||||
var/lib/node_*
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
[submodule "libraries/rapidjson"]
|
||||
path = libraries/rapidjson
|
||||
url = https://github.com/Tencent/rapidjson/
|
||||
[submodule "libraries/yubihsm"]
|
||||
path = libraries/yubihsm
|
||||
url = https://github.com/Yubico/yubihsm-shell
|
||||
[submodule "tests/abieos"]
|
||||
path = tests/abieos
|
||||
url = https://github.com/AntelopeIO/abieos
|
||||
@@ -25,3 +28,6 @@
|
||||
[submodule "libraries/libfc/libraries/ff"]
|
||||
path = libraries/libfc/libraries/ff
|
||||
url = https://github.com/AntelopeIO/libff
|
||||
[submodule "libraries/prometheus-cpp"]
|
||||
path = libraries/prometheus-cpp
|
||||
url = https://github.com/jupp0r/prometheus-cpp.git
|
||||
|
||||
+8
-2
@@ -13,8 +13,8 @@ set( CMAKE_CXX_STANDARD 17 )
|
||||
set( CMAKE_CXX_EXTENSIONS ON )
|
||||
set( CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(VERSION_MAJOR 4)
|
||||
set(VERSION_MINOR 0)
|
||||
set(VERSION_MAJOR 3)
|
||||
set(VERSION_MINOR 2)
|
||||
set(VERSION_PATCH 0)
|
||||
set(VERSION_SUFFIX dev)
|
||||
|
||||
@@ -60,6 +60,8 @@ if(APPLE AND UNIX AND "${OPENSSL_ROOT_DIR}" STREQUAL "")
|
||||
set(OPENSSL_ROOT_DIR "/usr/local/opt/openssl@3;/usr/local/opt/openssl@1.1")
|
||||
endif()
|
||||
endif()
|
||||
# fc also adds these definitions to its public interface. once fc becomes the sole importer of openssl, this should be removed
|
||||
add_definitions(-DOPENSSL_API_COMPAT=0x10100000L -DOPENSSL_NO_DEPRECATED)
|
||||
|
||||
option(ENABLE_OC "Enable eosvm-oc on supported platforms" ON)
|
||||
|
||||
@@ -222,6 +224,7 @@ configure_file(libraries/libfc/src/network/LICENSE.go licen
|
||||
configure_file(libraries/eos-vm/LICENSE licenses/leap/LICENSE.eos-vm COPYONLY)
|
||||
configure_file(libraries/libfc/libraries/ff/LICENSE licenses/leap/LICENSE.libff COPYONLY)
|
||||
configure_file(programs/cleos/LICENSE.CLI11 licenses/leap/LICENSE.CLI11 COPYONLY)
|
||||
configure_file(libraries/yubihsm/LICENSE licenses/leap/LICENSE.yubihsm COPYONLY)
|
||||
|
||||
install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/licenses/leap" DESTINATION "${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/" COMPONENT base)
|
||||
|
||||
@@ -240,6 +243,9 @@ add_custom_target(dev-install
|
||||
USES_TERMINAL
|
||||
)
|
||||
|
||||
get_property(_CTEST_CUSTOM_TESTS_IGNORE GLOBAL PROPERTY CTEST_CUSTOM_TESTS_IGNORE)
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/CTestCustom.cmake" "SET(CTEST_CUSTOM_TESTS_IGNORE ${_CTEST_CUSTOM_TESTS_IGNORE})")
|
||||
|
||||
include(doxygen)
|
||||
|
||||
include(package.cmake)
|
||||
|
||||
@@ -51,7 +51,7 @@ find_package(Boost @Boost_MAJOR_VERSION@.@Boost_MINOR_VERSION@ EXACT REQUIRED CO
|
||||
|
||||
find_library(libtester eosio_testing @CMAKE_BINARY_DIR@/libraries/testing NO_DEFAULT_PATH)
|
||||
find_library(libchain eosio_chain @CMAKE_BINARY_DIR@/libraries/chain NO_DEFAULT_PATH)
|
||||
find_library(libfc fc @CMAKE_BINARY_DIR@/libraries/libfc NO_DEFAULT_PATH)
|
||||
find_library(libfc fc @CMAKE_BINARY_DIR@/libraries/fc NO_DEFAULT_PATH)
|
||||
find_library(libsecp256k1 secp256k1 @CMAKE_BINARY_DIR@/libraries/libfc/secp256k1 NO_DEFAULT_PATH)
|
||||
|
||||
find_library(libff ff @CMAKE_BINARY_DIR@/libraries/libfc/libraries/ff/libff NO_DEFAULT_PATH)
|
||||
|
||||
@@ -1,249 +1,126 @@
|
||||
# Leap
|
||||
Leap is a C++ implementation of the [Antelope](https://github.com/AntelopeIO) protocol. It contains blockchain node software and supporting tools for developers and node operators.
|
||||
|
||||
## Branches
|
||||
The `main` branch is the development branch; do not use it for production. Refer to the [release page](https://github.com/AntelopeIO/leap/releases) for current information on releases, pre-releases, and obsolete releases, as well as the corresponding tags for those releases.
|
||||
Leap is blockchain node software and supporting tools that implements the [Antelope](https://github.com/AntelopeIO) protocol.
|
||||
|
||||
## Supported Operating Systems
|
||||
We currently support the following operating systems.
|
||||
- Ubuntu 22.04 Jammy
|
||||
- Ubuntu 20.04 Focal
|
||||
- Ubuntu 18.04 Bionic
|
||||
## Repo Organization
|
||||
|
||||
Other Unix derivatives such as macOS are tended to on a best-effort basis and may not be full featured. If you aren't using Ubuntu, please visit the "[Build Unsupported OS](./docs/00_install/01_build-from-source/00_build-unsupported-os.md)" page to explore your options.
|
||||
`main` branch is the development branch: do not use this for production. Refer to the [release page](https://github.com/AntelopeIO/leap/releases) for current information on releases, pre-releases, and obsolete releases as well as the corresponding tags for those releases.
|
||||
|
||||
If you are running an unsupported Ubuntu derivative, such as Linux Mint, you can find the version of Ubuntu your distribution was based on by using this command:
|
||||
```bash
|
||||
cat /etc/upstream-release/lsb-release
|
||||
## Software Installation
|
||||
|
||||
Visit the [release page](https://github.com/AntelopeIO/leap/releases) for Ubuntu binaries. This is the fastest way to get started with the software.
|
||||
|
||||
### Building From Source
|
||||
|
||||
Recent Ubuntu LTS releases are the only Linux distributions that we fully support. Other Linux distros and other POSIX operating systems (such as macOS) are tended to on a best-effort basis and may not be full featured. Notable requirements to build are:
|
||||
* C++17 compiler and standard library
|
||||
* boost 1.67+
|
||||
* CMake 3.8+
|
||||
* (for Linux only) LLVM 7 - 11 (newer versions do not work)
|
||||
|
||||
A few other common libraries are tools also required such as openssl 1.1+, libcurl, curl, libusb, GMP, Python 3, and zlib.
|
||||
|
||||
**A Warning On Parallel Compilation Jobs (`-j` flag)**: When building C/C++ software often the build is performed in parallel via a command such as `make -j $(nproc)` which uses the number of CPU cores as the number of compilation jobs to perform simultaneously. However, be aware that some compilation units (.cpp files) in Leap are extremely complex and will consume nearly 4GB of memory to compile. You may need to reduce the level of parallelization depending on the amount of memory on your build host. e.g. instead of `make -j $(nproc)` run `make -j2`. Failures due to memory exhaustion will typically but not always manifest as compiler crashes.
|
||||
|
||||
Generally we recommend performing what we refer to as a "pinned build" which ensures the compiler and boost version remain the same between builds of different Leap versions (Leap requires these versions remain the same otherwise its state needs to be repopulated from a portable snapshot).
|
||||
|
||||
#### Building Pinned Build Binary Packages
|
||||
In the directory `<leap src>/scripts` you will find the two scripts `install_deps.sh` and `pinned_build.sh`. If you haven't installed build dependencies then run `install_deps.sh`. Then run `pinned_build.sh <dependencies directory> <leap build directory> <number of jobs>`.
|
||||
|
||||
The dependencies directory is where the script will pull the C++ dependencies that need to be built with the pinned compiler for building the pinned binaries for binary packaging.
|
||||
|
||||
The binary package will be produced in the Leap build directory that was supplied.
|
||||
|
||||
#### Manual (non "pinned") Build Instructions
|
||||
|
||||
<details>
|
||||
<summary>Ubuntu 20.04 & 22.04 Build Instructions</summary>
|
||||
|
||||
Install required dependencies:
|
||||
```
|
||||
Your best bet is to follow the instructions for your Ubuntu base, but we make no guarantees.
|
||||
|
||||
## Binary Installation
|
||||
This is the fastest way to get started. From the [latest release](https://github.com/AntelopeIO/leap/releases/latest) page, download a binary for one of our [supported operating systems](#supported-operating-systems), or visit the [release tags](https://github.com/AntelopeIO/leap/releases) page to download a binary for a specific version of Leap.
|
||||
|
||||
Once you have a `*.deb` file downloaded for your version of Ubuntu, you can install it as follows:
|
||||
```bash
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ~/Downloads/leap*.deb
|
||||
apt-get update && apt-get install \
|
||||
build-essential \
|
||||
cmake \
|
||||
curl \
|
||||
git \
|
||||
libboost-all-dev \
|
||||
libcurl4-openssl-dev \
|
||||
libgmp-dev \
|
||||
libssl-dev \
|
||||
libusb-1.0-0-dev \
|
||||
llvm-11-dev \
|
||||
pkg-config
|
||||
```
|
||||
Your download path may vary. If you are in an Ubuntu docker container, omit `sudo` because you run as `root` by default.
|
||||
|
||||
Finally, verify Leap was installed correctly:
|
||||
```bash
|
||||
nodeos --full-version
|
||||
and perform the build:
|
||||
```
|
||||
You should see a [semantic version](https://semver.org) string followed by a `git` commit hash with no errors. For example:
|
||||
```
|
||||
v3.1.2-0b64f879e3ebe2e4df09d2e62f1fc164cc1125d1
|
||||
```
|
||||
|
||||
## Build and Install from Source
|
||||
You can also build and install Leap from source.
|
||||
|
||||
### Prerequisites
|
||||
You will need to build on a [supported operating system](#supported-operating-systems).
|
||||
|
||||
Requirements to build:
|
||||
- C++17 compiler and standard library
|
||||
- boost 1.67+
|
||||
- CMake 3.8+
|
||||
- LLVM 7 - 11 - for Linux only
|
||||
- newer versions do not work
|
||||
- openssl 1.1+
|
||||
- curl
|
||||
- git
|
||||
- GMP
|
||||
- Python 3
|
||||
- zlib
|
||||
|
||||
### Step 1 - Clone
|
||||
If you don't have the Leap repo cloned to your computer yet, [open a terminal](https://itsfoss.com/open-terminal-ubuntu) and navigate to the folder where you want to clone the Leap repository:
|
||||
```bash
|
||||
cd ~/Downloads
|
||||
```
|
||||
Clone Leap using either HTTPS...
|
||||
```bash
|
||||
git clone --recursive https://github.com/AntelopeIO/leap.git
|
||||
```
|
||||
...or SSH:
|
||||
```bash
|
||||
git clone --recursive git@github.com:AntelopeIO/leap.git
|
||||
```
|
||||
|
||||
> ℹ️ **HTTPS vs. SSH Clone** ℹ️
|
||||
Both an HTTPS or SSH git clone will yield the same result - a folder named `leap` containing our source code. It doesn't matter which type you use.
|
||||
|
||||
Navigate into that folder:
|
||||
```bash
|
||||
cd leap
|
||||
```
|
||||
|
||||
### Step 2 - Checkout Release Tag or Branch
|
||||
Choose which [release](https://github.com/AntelopeIO/leap/releases) or [branch](#branches) you would like to build, then check it out. If you are not sure, use the [latest release](https://github.com/AntelopeIO/leap/releases/latest). For example, if you want to build release 3.1.2 then you would check it out using its tag, `v3.1.2`. In the example below, replace `v0.0.0` with your selected release tag accordingly:
|
||||
```bash
|
||||
git fetch --all --tags
|
||||
git checkout v0.0.0
|
||||
```
|
||||
|
||||
Once you are on the branch or release tag you want to build, make sure everything is up-to-date:
|
||||
```bash
|
||||
git pull
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
### Step 3 - Build
|
||||
Select build instructions below for a [pinned build](#pinned-build) (preferred) or an [unpinned build](#unpinned-build).
|
||||
|
||||
> ℹ️ **Pinned vs. Unpinned Build** ℹ️
|
||||
We have two types of builds for Leap: "pinned" and "unpinned." The only difference is that pinned builds use specific versions for some dependencies hand-picked by the Leap engineers - they are "pinned" to those versions. In contrast, unpinned builds use the default dependency versions available on the build system at the time. We recommend performing a "pinned" build to ensure the compiler and boost versions remain the same between builds of different Leap versions. Leap requires these versions to remain the same, otherwise its state might need to be recovered from a portable snapshot or the chain needs to be replayed.
|
||||
|
||||
> ⚠️ **A Warning On Parallel Compilation Jobs (`-j` flag)** ⚠️
|
||||
When building C/C++ software, often the build is performed in parallel via a command such as `make -j "$(nproc)"` which uses all available CPU threads. However, be aware that some compilation units (`*.cpp` files) in Leap will consume nearly 4GB of memory. Failures due to memory exhaustion will typically, but not always, manifest as compiler crashes. Using all available CPU threads may also prevent you from doing other things on your computer during compilation. For these reasons, consider reducing this value.
|
||||
|
||||
> 🐋 **Docker and `sudo`** 🐋
|
||||
If you are in an Ubuntu docker container, omit `sudo` from all commands because you run as `root` by default. Most other docker containers also exclude `sudo`, especially Debian-family containers. If your shell prompt is a hash tag (`#`), omit `sudo`.
|
||||
|
||||
#### Pinned Build
|
||||
Make sure you are in the root of the `leap` repo, then run the `install_depts.sh` script to install dependencies:
|
||||
```bash
|
||||
sudo scripts/install_deps.sh
|
||||
```
|
||||
|
||||
Next, run the pinned build script. You have to give it three arguments, in the following order:
|
||||
- A temporary folder, for all dependencies that need to be built from source.
|
||||
- A build folder, where the binaries you need to install will be built to.
|
||||
- The number of jobs or CPU cores/threads to use (note the [jobs flag](#step-3---build) warning above).
|
||||
|
||||
The following command runs the `pinned_build.sh` script, specifies a `deps` and `build` folder in the root of the Leap repo for the first two arguments, then builds the packages using all of your computer's CPU threads (Note: you don't need `sudo` for this command):
|
||||
```bash
|
||||
scripts/pinned_build.sh deps build "$(nproc)"
|
||||
```
|
||||
Now you can optionally [test](#step-4---test) your build, or [install](#step-5---install) the `*.deb` binary packages, which will be in the root of your build directory.
|
||||
|
||||
#### Unpinned Build
|
||||
The following instructions are valid for this branch. Other release branches may have different requirements, so ensure you follow the directions in the branch or release you intend to build. If you are in an Ubuntu docker container, omit `sudo` because you run as `root` by default.
|
||||
|
||||
<details> <summary>Ubuntu 22.04 Jammy & Ubuntu 20.04 Focal</summary>
|
||||
|
||||
Install dependencies:
|
||||
```bash
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
build-essential \
|
||||
cmake \
|
||||
curl \
|
||||
git \
|
||||
libboost-all-dev \
|
||||
libgmp-dev \
|
||||
libssl-dev \
|
||||
llvm-11-dev
|
||||
```
|
||||
To build, make sure you are in the root of the `leap` repo, then run the following command:
|
||||
```bash
|
||||
mkdir -p build
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=/usr/lib/llvm-11 ..
|
||||
make -j "$(nproc)" package
|
||||
make -j $(nproc) package
|
||||
```
|
||||
</details>
|
||||
|
||||
<details> <summary>Ubuntu 18.04 Bionic</summary>
|
||||
<details>
|
||||
<summary>Ubuntu 18.04 Build Instructions</summary>
|
||||
|
||||
Install dependencies:
|
||||
```bash
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
build-essential \
|
||||
cmake \
|
||||
curl \
|
||||
g++-8 \
|
||||
git \
|
||||
libgmp-dev \
|
||||
libssl-dev \
|
||||
llvm-7-dev \
|
||||
python3 \
|
||||
Install required dependencies. You will need to build Boost from source on this distribution.
|
||||
```
|
||||
apt-get update && apt-get install \
|
||||
build-essential \
|
||||
cmake \
|
||||
curl \
|
||||
g++-8 \
|
||||
git \
|
||||
libcurl4-openssl-dev \
|
||||
libgmp-dev \
|
||||
libssl-dev \
|
||||
libusb-1.0-0-dev \
|
||||
llvm-7-dev \
|
||||
pkg-config \
|
||||
python3 \
|
||||
zlib1g-dev
|
||||
|
||||
curl -L https://boostorg.jfrog.io/artifactory/main/release/1.79.0/source/boost_1_79_0.tar.bz2 | tar jx && \
|
||||
cd boost_1_79_0 && \
|
||||
./bootstrap.sh --prefix=$HOME/boost1.79 && \
|
||||
./b2 --with-iostreams --with-date_time --with-filesystem --with-system \
|
||||
--with-program_options --with-chrono --with-test -j$(nproc) install && \
|
||||
cd ..
|
||||
```
|
||||
You need to build Boost from source on this distribution:
|
||||
```bash
|
||||
curl -fL https://boostorg.jfrog.io/artifactory/main/release/1.79.0/source/boost_1_79_0.tar.bz2 -o ~/Downloads/boost_1_79_0.tar.bz2
|
||||
tar -jvxf ~/Downloads/boost_1_79_0.tar.bz2 -C ~/Downloads/
|
||||
pushd ~/Downloads/boost_1_79_0
|
||||
./bootstrap.sh --prefix="$HOME/boost1.79"
|
||||
./b2 --with-iostreams --with-date_time --with-filesystem --with-system --with-program_options --with-chrono --with-test -j "$(nproc)" install
|
||||
popd
|
||||
and perform the build:
|
||||
```
|
||||
The Boost `*.tar.bz2` download and `boost_1_79_0` folder can be removed now if you want more space.
|
||||
```bash
|
||||
rm -r ~/Downloads/boost_1_79_0.tar.bz2 ~/Downloads/boost_1_79_0
|
||||
```
|
||||
From a terminal in the root of the `leap` repo, build.
|
||||
```bash
|
||||
mkdir -p build
|
||||
git submodule update --init --recursive
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_C_COMPILER=gcc-8 -DCMAKE_CXX_COMPILER=g++-8 -DCMAKE_PREFIX_PATH="$HOME/boost1.79;/usr/lib/llvm-7/" -DCMAKE_BUILD_TYPE=Release ..
|
||||
make -j "$(nproc)" package
|
||||
cmake -DCMAKE_C_COMPILER=gcc-8 -DCMAKE_CXX_COMPILER=g++-8 \
|
||||
-DCMAKE_PREFIX_PATH="$HOME/boost1.79;/usr/lib/llvm-7/" -DCMAKE_BUILD_TYPE=Release .. \
|
||||
make -j $(nproc) package
|
||||
```
|
||||
After building, you may remove the `~/boost1.79` directory or you may keep it around for your next build.
|
||||
After building you may remove the `$HOME/boost1.79` directory, or you may keep it around until next time building the software.
|
||||
</details>
|
||||
|
||||
Now you can optionally [test](#step-4---test) your build, or [install](#step-5---install) the `*.deb` binary packages, which will be in the root of your build directory.
|
||||
### Running Tests
|
||||
|
||||
### Step 4 - Test
|
||||
Leap supports the following test suites:
|
||||
When building from source it's recommended to run at least what we refer to as the "parallelizable tests". Not included by default in the "parallelizable tests" are the WASM spec tests which can add additional coverage and can also be run in parallel.
|
||||
|
||||
Test Suite | Test Type | [Test Size](https://testing.googleblog.com/2010/12/test-sizes.html) | Notes
|
||||
---|:---:|:---:|---
|
||||
[Parallelizable tests](#parallelizable-tests) | Unit tests | Small
|
||||
[WASM spec tests](#wasm-spec-tests) | Unit tests | Small | Unit tests for our WASM runtime, each short but _very_ CPU-intensive
|
||||
[Serial tests](#serial-tests) | Component/Integration | Medium
|
||||
[Long-running tests](#long-running-tests) | Integration | Medium-to-Large | Tests which take an extraordinarily long amount of time to run
|
||||
```
|
||||
cd build
|
||||
|
||||
When building from source, we recommended running at least the [parallelizable tests](#parallelizable-tests).
|
||||
# "parallelizable tests": the minimum test set that should be run
|
||||
ctest -j $(nproc) -LE _tests
|
||||
|
||||
#### Parallelizable Tests
|
||||
This test suite consists of any test that does not require shared resources, such as file descriptors, specific folders, or ports, and can therefore be run concurrently in different threads without side effects (hence, easily parallelized). These are mostly unit tests and [small tests](https://testing.googleblog.com/2010/12/test-sizes.html) which complete in a short amount of time.
|
||||
|
||||
You can invoke them by running `ctest` from a terminal in your Leap build directory and specifying the following arguments:
|
||||
```bash
|
||||
ctest -j "$(nproc)" -LE _tests
|
||||
# Also consider running the WASM spec tests for more coverage
|
||||
ctest -j $(nproc) -L wasm_spec_tests
|
||||
```
|
||||
|
||||
#### WASM Spec Tests
|
||||
The WASM spec tests verify that our WASM execution engine is compliant with the web assembly standard. These are very [small](https://testing.googleblog.com/2010/12/test-sizes.html), very fast unit tests. However, there are over a thousand of them so the suite can take a little time to run. These tests are extremely CPU-intensive.
|
||||
|
||||
You can invoke them by running `ctest` from a terminal in your Leap build directory and specifying the following arguments:
|
||||
```bash
|
||||
ctest -j "$(nproc)" -L wasm_spec_tests
|
||||
Some other tests are available and recommended but be aware they can be sensitive to other software running on the same host and they may **SIGKILL** other nodeos instances running on the host.
|
||||
```
|
||||
We have observed severe performance issues when multiple virtual machines are running this test suite on the same physical host at the same time, for example in a CICD system. This can be resolved by disabling hyperthreading on the host.
|
||||
cd build
|
||||
|
||||
#### Serial Tests
|
||||
The serial test suite consists of [medium](https://testing.googleblog.com/2010/12/test-sizes.html) component or integration tests that use specific paths, ports, rely on process names, or similar, and cannot be run concurrently with other tests. Serial tests can be sensitive to other software running on the same host and they may `SIGKILL` other `nodeos` processes. These tests take a moderate amount of time to complete, but we recommend running them.
|
||||
|
||||
You can invoke them by running `ctest` from a terminal in your Leap build directory and specifying the following arguments:
|
||||
```bash
|
||||
# These tests can't run in parallel but are recommended.
|
||||
ctest -L "nonparallelizable_tests"
|
||||
```
|
||||
|
||||
#### Long-Running Tests
|
||||
The long-running tests are [medium-to-large](https://testing.googleblog.com/2010/12/test-sizes.html) integration tests that rely on shared resources and take a very long time to run.
|
||||
|
||||
You can invoke them by running `ctest` from a terminal in your Leap build directory and specifying the following arguments:
|
||||
```bash
|
||||
# These tests can't run in parallel. They also take a long time to run.
|
||||
ctest -L "long_running_tests"
|
||||
```
|
||||
|
||||
### Step 5 - Install
|
||||
Once you have [built](#step-3---build-the-source-code) Leap and [tested](#step-4---test) your build, you can install Leap on your system. Don't forget to omit `sudo` if you are running in a docker container.
|
||||
|
||||
We recommend installing the binary package you just built. Navigate to your Leap build directory in a terminal and run this command:
|
||||
```bash
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ./leap[-_][0-9]*.deb
|
||||
```
|
||||
|
||||
It is also possible to install using `make` instead:
|
||||
```bash
|
||||
sudo make install
|
||||
```
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"name": "eos",
|
||||
"generators": [
|
||||
{
|
||||
"name": "collate_markdown",
|
||||
"options": {
|
||||
"docs_dir": "docs"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swagger",
|
||||
"options": {
|
||||
"swagger_path": "plugins/chain_api_plugin/chain.swagger.yaml",
|
||||
"swagger_dest_path": "nodeos/plugins/chain_api_plugin/api-reference",
|
||||
"disable_filters": true,
|
||||
"disable_summary_gen": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swagger",
|
||||
"options": {
|
||||
"swagger_path": "plugins/db_size_api_plugin/db_size.swagger.yaml",
|
||||
"swagger_dest_path": "nodeos/plugins/db_size_api_plugin/api-reference",
|
||||
"disable_filters": true,
|
||||
"disable_summary_gen": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swagger",
|
||||
"options": {
|
||||
"swagger_path": "plugins/producer_api_plugin/producer.swagger.yaml",
|
||||
"swagger_dest_path": "nodeos/plugins/producer_api_plugin/api-reference",
|
||||
"disable_filters": true,
|
||||
"disable_summary_gen": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swagger",
|
||||
"options": {
|
||||
"swagger_path": "plugins/net_api_plugin/net.swagger.yaml",
|
||||
"swagger_dest_path": "nodeos/plugins/net_api_plugin/api-reference",
|
||||
"disable_filters": true,
|
||||
"disable_summary_gen": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swagger",
|
||||
"options": {
|
||||
"swagger_path": "plugins/test_control_api_plugin/test_control.swagger.yaml",
|
||||
"swagger_dest_path": "nodeos/plugins/test_control_api_plugin/api-reference",
|
||||
"disable_filters": true,
|
||||
"disable_summary_gen": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swagger",
|
||||
"options": {
|
||||
"swagger_path": "plugins/trace_api_plugin/trace_api.swagger.yaml",
|
||||
"swagger_dest_path": "nodeos/plugins/trace_api_plugin/api-reference",
|
||||
"disable_filters": true,
|
||||
"disable_summary_gen": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -2,19 +2,123 @@
|
||||
content_title: Build Antelope from Source
|
||||
---
|
||||
|
||||
The shell scripts previously recommended for building the software have been removed in favor of a build process entirely driven by CMake. Those wishing to build from source are now responsible for installing the necessary dependencies. The list of dependencies and the recommended build procedure are in the [`README.md`](https://github.com/AntelopeIO/leap/blob/main/README.md) file. Instructions are also included for efficiently running the tests.
|
||||
The shell scripts previously recommended for building the software have been removed in favor of a build process entirely driven by CMake. Those wishing to build from source are now responsible for installing the necessary dependencies. The list of dependencies and the recommended build procedure are in the README.md file. Instructions are also included for efficiently running the tests.
|
||||
|
||||
### Using DUNE
|
||||
As an alternative to building from source, try [Docker Utilities for Node Execution](https://github.com/AntelopeIO/DUNE) for the easiest way to get started and for multi-platform support.
|
||||
|
||||
As an alternative to building from source try [Docker Utilities for Node Execution](https://github.com/AntelopeIO/DUNE) for the easiest way to get started, and for multi-platform support.
|
||||
|
||||
### Building From Source
|
||||
You can also build and install Leap from source. Instructions for that currently live [here](https://github.com/AntelopeIO/leap/blob/main/README.md#build-and-install-from-source).
|
||||
|
||||
Recent Ubuntu LTS releases are the only Linux distributions that we fully support. Other Linux distros and other POSIX operating systems (such as macOS) are tended to on a best-effort basis and may not be full featured. Notable requirements to build are:
|
||||
* C++17 compiler and standard library
|
||||
* boost 1.67+
|
||||
* CMake 3.8+
|
||||
* (for Linux only) LLVM 7 - 11 (newer versions do not work)
|
||||
|
||||
A few other common libraries are tools also required such as openssl 1.1+, libcurl, curl, libusb, GMP, Python 3, and zlib.
|
||||
|
||||
**A Warning On Parallel Compilation Jobs (`-j` flag)**: When building C/C++ software often the build is performed in parallel via a command such as `make -j $(nproc)` which uses the number of CPU cores as the number of compilation jobs to perform simultaneously. However, be aware that some compilation units (.cpp files) in mandel are extremely complex and will consume nearly 4GB of memory to compile. You may need to reduce the level of parallelization depending on the amount of memory on your build host. e.g. instead of `make -j $(nproc)` run `make -j2`. Failures due to memory exhaustion will typically but not always manifest as compiler crashes.
|
||||
|
||||
Generally we recommend performing what we refer to as a "pinned build" which ensures the compiler and boost version remain the same between builds of different mandel versions (mandel requires these versions remain the same otherwise its state needs to be repopulated from a portable snapshot).
|
||||
|
||||
#### Building Pinned Build Binary Packages
|
||||
The pinned build instructions have moved [here](https://github.com/AntelopeIO/leap/blob/main/README.md#pinned-build). You may want to look at the [prerequisites](https://github.com/AntelopeIO/leap/blob/main/README.md#prerequisites) and our warning on parallelization using the `-j` jobs flag [here](https://github.com/AntelopeIO/leap/blob/main/README.md#step-3---build) before you build.
|
||||
In the directory `<mandel src>/scripts` you will find the two scripts `install_deps.sh` and `pinned_build.sh`. If you haven't installed build dependencies then run `install_deps.sh`. Then run `pinned_build.sh <dependencies directory> <mandel build directory> <number of jobs>`.
|
||||
|
||||
The dependencies directory is where the script will pull the C++ dependencies that need to be built with the pinned compiler for building the pinned binaries for binary packaging.
|
||||
|
||||
The binary package will be produced in the mandel build directory that was supplied.
|
||||
|
||||
#### Manual (non "pinned") Build Instructions
|
||||
The unpinned build instructions have moved [here](https://github.com/AntelopeIO/leap/blob/main/README.md#unpinned-build). You may want to look at the [prerequisites](https://github.com/AntelopeIO/leap/blob/main/README.md#prerequisites) and our warning on parallelization using the `-j` jobs flag [here](https://github.com/AntelopeIO/leap/blob/main/README.md#step-3---build) before you build.
|
||||
|
||||
<details>
|
||||
<summary>Ubuntu 20.04 & 22.04 Build Instructions</summary>
|
||||
|
||||
Install required dependencies:
|
||||
```
|
||||
apt-get update && apt-get install \
|
||||
build-essential \
|
||||
cmake \
|
||||
curl \
|
||||
git \
|
||||
libboost-all-dev \
|
||||
libcurl4-openssl-dev \
|
||||
libgmp-dev \
|
||||
libssl-dev \
|
||||
libusb-1.0-0-dev \
|
||||
llvm-11-dev \
|
||||
pkg-config
|
||||
```
|
||||
and perform the build:
|
||||
```
|
||||
git submodule update --init --recursive
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||
make -j $(nproc) package
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Ubuntu 18.04 Build Instructions</summary>
|
||||
|
||||
Install required dependencies. You will need to build Boost from source on this distribution.
|
||||
```
|
||||
apt-get update && apt-get install \
|
||||
build-essential \
|
||||
cmake \
|
||||
curl \
|
||||
g++-8 \
|
||||
git \
|
||||
libcurl4-openssl-dev \
|
||||
libgmp-dev \
|
||||
libssl-dev \
|
||||
libusb-1.0-0-dev \
|
||||
llvm-7-dev \
|
||||
pkg-config \
|
||||
python3 \
|
||||
zlib1g-dev
|
||||
|
||||
curl -L https://boostorg.jfrog.io/artifactory/main/release/1.79.0/source/boost_1_79_0.tar.bz2 | tar jx && \
|
||||
cd boost_1_79_0 && \
|
||||
./bootstrap.sh --prefix=$HOME/boost1.79 && \
|
||||
./b2 --with-iostreams --with-date_time --with-filesystem --with-system \
|
||||
--with-program_options --with-chrono --with-test -j$(nproc) install && \
|
||||
cd ..
|
||||
```
|
||||
and perform the build:
|
||||
```
|
||||
git submodule update --init --recursive
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_C_COMPILER=gcc-8 -DCMAKE_CXX_COMPILER=g++-8 \
|
||||
-DCMAKE_PREFIX_PATH="$HOME/boost1.79;/usr/lib/llvm-7/" -DCMAKE_BUILD_TYPE=Release .. \
|
||||
make -j $(nproc) package
|
||||
```
|
||||
After building you may remove the `$HOME/boost1.79` directory, or you may keep it around until next time building the software.
|
||||
</details>
|
||||
|
||||
### Running Tests
|
||||
Documentation on available test suites and how to run them has moved [here](https://github.com/AntelopeIO/leap/blob/main/README.md#test).
|
||||
|
||||
When building from source it's recommended to run at least what we refer to as the "parallelizable tests". Not included by default in the "parallelizable tests" are the WASM spec tests which can add additional coverage and can also be run in parallel.
|
||||
|
||||
```
|
||||
cd build
|
||||
|
||||
# "parallelizable tests": the minimum test set that should be run
|
||||
ctest -j $(nproc) -LE _tests
|
||||
|
||||
# Also consider running the WASM spec tests for more coverage
|
||||
ctest -j $(nproc) -L wasm_spec_tests
|
||||
```
|
||||
|
||||
Some other tests are available and recommended but be aware they can be sensitive to other software running on the same host and they may **SIGKILL** other nodeos instances running on the host.
|
||||
```
|
||||
cd build
|
||||
|
||||
# These tests can't run in parallel but are recommended.
|
||||
ctest -L "nonparallelizable_tests"
|
||||
|
||||
# These tests can't run in parallel. They also take a long time to run.
|
||||
ctest -L "long_running_tests"
|
||||
```
|
||||
|
||||
@@ -10,9 +10,9 @@ The best way to install and use the Antelope software is to build it from source
|
||||
|
||||
Antelope currently supports the following operating systems:
|
||||
|
||||
1. Ubuntu 22.04 Jammy
|
||||
2. Ubuntu 20.04 Focal
|
||||
3. Ubuntu 18.04 Bionic
|
||||
1. Ubuntu 18.04
|
||||
2. Ubuntu 20.04
|
||||
3. Ubuntu 22.04
|
||||
|
||||
[[info | Note]]
|
||||
| It may be possible to build and install Antelope on other Unix-based operating systems. We gathered helpful information on the following page but please keep in mind that it is experimental and not officially supported.
|
||||
|
||||
@@ -13,6 +13,7 @@ For information on specific plugins, just select from the list below:
|
||||
* [`db_size_api_plugin`](db_size_api_plugin/index.md)
|
||||
* [`http_client_plugin`](http_client_plugin/index.md)
|
||||
* [`http_plugin`](http_plugin/index.md)
|
||||
* [`login_plugin`](login_plugin/index.md)
|
||||
* [`net_api_plugin`](net_api_plugin/index.md)
|
||||
* [`net_plugin`](net_plugin/index.md)
|
||||
* [`producer_plugin`](producer_plugin/index.md)
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
## Description
|
||||
|
||||
The `login_plugin` supports the concept of applications authenticating with the Antelope blockchain. The `login_plugin` API allows an application to verify whether an account is allowed to sign in order to satisfy a specified authority.
|
||||
|
||||
## Usage
|
||||
|
||||
```console
|
||||
# config.ini
|
||||
plugin = eosio::login_plugin
|
||||
[options]
|
||||
```
|
||||
```sh
|
||||
# command-line
|
||||
nodeos ... --plugin eosio::login_plugin [options]
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
These can be specified from both the `nodeos` command-line or the `config.ini` file:
|
||||
|
||||
```console
|
||||
Config Options for eosio::login_plugin:
|
||||
--max-login-requests arg (=1000000) The maximum number of pending login
|
||||
requests
|
||||
--max-login-timeout arg (=60) The maximum timeout for pending login
|
||||
requests (in seconds)
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
* [`chain_plugin`](../chain_plugin/index.md)
|
||||
* [`http_plugin`](../http_plugin/index.md)
|
||||
|
||||
### Load Dependency Examples
|
||||
|
||||
```console
|
||||
# config.ini
|
||||
plugin = eosio::chain_plugin
|
||||
[options]
|
||||
plugin = eosio::http_plugin
|
||||
[options]
|
||||
```
|
||||
```sh
|
||||
# command-line
|
||||
nodeos ... --plugin eosio::chain_plugin [options] \
|
||||
--plugin eosio::http_plugin [options]
|
||||
```
|
||||
@@ -91,6 +91,11 @@ Config Options for eosio::wallet_plugin:
|
||||
number of seconds of inactivity.
|
||||
Activity is defined as any wallet
|
||||
command e.g. list-wallets.
|
||||
--yubihsm-url URL Override default URL of
|
||||
http://localhost:12345 for connecting
|
||||
to yubihsm-connector
|
||||
--yubihsm-authkey key_num Enables YubiHSM support using given
|
||||
Authkey
|
||||
|
||||
Application Config Options:
|
||||
--plugin arg Plugin(s) to enable, may be specified
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
---
|
||||
content_title: How To Attach a YubiHSM Hard Wallet
|
||||
link_text: How To Attach a YubiHSM Hard Wallet
|
||||
---
|
||||
|
||||
## Goal
|
||||
|
||||
Attach a YubiHSM as a hard wallet
|
||||
|
||||
## Before you begin
|
||||
|
||||
* Install the currently supported version of `keosd`
|
||||
|
||||
* Install YubiHSM2 Software Toolkit (YubiHSM2 SDK)
|
||||
|
||||
* Create an AuthKey with at least the following Capabilities:
|
||||
|
||||
* sign-ecdsa
|
||||
* generate-asymmetric-key
|
||||
* export-wrapped
|
||||
|
||||
* **Delete the default AuthKey**
|
||||
|
||||
[[warning | Security]]
|
||||
| It is extremely important to create a new AuthKey and remove the default AuthKey before proceed to the following steps.
|
||||
|
||||
## Steps
|
||||
|
||||
### Configure `keosd`
|
||||
|
||||
There are two options to connect `keosd` to YubiHSM:
|
||||
|
||||
#### Using a YubiHSM connector
|
||||
|
||||
By default, `keosd` will connect to the YubiHSM connector on the default host and port. If a non-default URL is used, set the `--yubihsm-url` option or `yubihsm-url` in `config.ini` with the correct connector URL
|
||||
|
||||
#### Directly connect via USB
|
||||
|
||||
`keosd` also can directly connect to YubiHSM via USB protocol
|
||||
|
||||
If this option is used, set `keosd` startup option as the below:
|
||||
|
||||
```sh
|
||||
--yubihsm-url=ysb://
|
||||
```
|
||||
|
||||
### Start `keosd` with AuthKey:
|
||||
|
||||
```sh
|
||||
--yubihsm-authkey Your_AuthKey_Object_Number
|
||||
```
|
||||
|
||||
if a YubiHSM connector is used, check the YubiHSM connector is up and running by visiting YubiHSM URL:
|
||||
http://YubiHSM_HOST:YubiHSM_PORT/connector/status ((Default HOST and Port: http://127.0.0.1:12345)
|
||||
|
||||
You should see something like this:
|
||||
|
||||
```console
|
||||
status=OK
|
||||
serial=*
|
||||
version=2.0.0
|
||||
pid=666
|
||||
address=localhost
|
||||
port=12345
|
||||
```
|
||||
|
||||
### Unlock YubiHSM wallet with the password of AuthKey using the following option:
|
||||
|
||||
```sh
|
||||
cleos wallet unlock -n YubiHSM --password YOUR_AUTHKEY_PASSWORD
|
||||
```
|
||||
|
||||
After unlocking the wallet, you can use `cleos wallet` commands as usual. Beware as a part of security mechanism, some wallet subcommands, such as retrieve private keys, or remove a key, are not supported when a YubiHSM is used
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
content_title: Keosd How-to Guides
|
||||
---
|
||||
|
||||
* [How to attach a YubiHSM hard wallet](how-to-attach-a-yubihsm-hard-wallet.md)
|
||||
+7
-7
@@ -4,8 +4,8 @@
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = "LEAP"
|
||||
PROJECT_NUMBER = "${DOXY_EOS_VERSION}"
|
||||
PROJECT_NAME = "EOS.IO"
|
||||
PROJECT_NUMBER = "EOSIO ${DOXY_EOS_VERSION}"
|
||||
PROJECT_BRIEF =
|
||||
PROJECT_LOGO = eos-logo.png
|
||||
OUTPUT_DIRECTORY =
|
||||
@@ -209,9 +209,9 @@ HTML_DYNAMIC_SECTIONS = NO
|
||||
HTML_INDEX_NUM_ENTRIES = 100
|
||||
GENERATE_DOCSET = NO
|
||||
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||
DOCSET_BUNDLE_ID = io.antelope
|
||||
DOCSET_PUBLISHER_ID = com.eosnetwork
|
||||
DOCSET_PUBLISHER_NAME = eosnetwork.com
|
||||
DOCSET_BUNDLE_ID = io.eos
|
||||
DOCSET_PUBLISHER_ID = one.block
|
||||
DOCSET_PUBLISHER_NAME = block.one
|
||||
GENERATE_HTMLHELP = NO
|
||||
CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
@@ -221,14 +221,14 @@ BINARY_TOC = NO
|
||||
TOC_EXPAND = NO
|
||||
GENERATE_QHP = NO
|
||||
QCH_FILE =
|
||||
QHP_NAMESPACE = io.antelope
|
||||
QHP_NAMESPACE = io.eos
|
||||
QHP_VIRTUAL_FOLDER = doc
|
||||
QHP_CUST_FILTER_NAME =
|
||||
QHP_CUST_FILTER_ATTRS =
|
||||
QHP_SECT_FILTER_ATTRS =
|
||||
QHG_LOCATION =
|
||||
GENERATE_ECLIPSEHELP = NO
|
||||
ECLIPSE_DOC_ID = io.antelope
|
||||
ECLIPSE_DOC_ID = io.eos
|
||||
DISABLE_INDEX = NO
|
||||
GENERATE_TREEVIEW = NO
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
|
||||
@@ -26,3 +26,25 @@ set(ENABLE_PROFILE OFF CACHE BOOL "Enable for profile builds")
|
||||
if(eos-vm IN_LIST EOSIO_WASM_RUNTIMES OR eos-vm-jit IN_LIST EOSIO_WASM_RUNTIMES)
|
||||
add_subdirectory( eos-vm )
|
||||
endif()
|
||||
|
||||
#yubihsm's openssl discovery is via pkg-config instead of find_package. Help it out on macOS otherwise openssl's pkgconfig
|
||||
# files may not be found down in the /opt/homebrew/opt directory
|
||||
if(APPLE)
|
||||
get_filename_component(OPENSSL_LIB_PATH "${OPENSSL_CRYPTO_LIBRARY}" DIRECTORY)
|
||||
set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:${OPENSSL_LIB_PATH}/pkgconfig")
|
||||
endif()
|
||||
set(ENABLE_STATIC ON)
|
||||
set(CMAKE_MACOSX_RPATH OFF)
|
||||
set(BUILD_ONLY_LIB ON CACHE BOOL "Library only build")
|
||||
message(STATUS "Starting yubihsm configuration...")
|
||||
add_subdirectory( yubihsm EXCLUDE_FROM_ALL )
|
||||
target_compile_options(yubihsm_static PRIVATE -fno-lto -fcommon)
|
||||
message(STATUS "yubihsm configuration complete")
|
||||
|
||||
get_property(_CTEST_CUSTOM_TESTS_IGNORE GLOBAL PROPERTY CTEST_CUSTOM_TESTS_IGNORE)
|
||||
set_property(GLOBAL PROPERTY CTEST_CUSTOM_TESTS_IGNORE
|
||||
"change_authkey import_ed decrypt_ec decrypt_rsa ssh logs generate_rsa import_ec echo\
|
||||
yubico_otp wrap_data wrap info import_rsa import_authkey generate_hmac generate_ec\
|
||||
attest pbkdf2 parsing ${_CTEST_CUSTOM_TESTS_IGNORE}")
|
||||
|
||||
add_subdirectory(prometheus)
|
||||
@@ -157,7 +157,6 @@ struct pending_state {
|
||||
block_stage_type _block_stage;
|
||||
controller::block_status _block_status = controller::block_status::incomplete;
|
||||
std::optional<block_id_type> _producer_block_id;
|
||||
controller::block_report _block_report{};
|
||||
|
||||
/** @pre _block_stage cannot hold completed_block alternative */
|
||||
const pending_block_header_state& get_pending_block_header_state()const {
|
||||
@@ -230,7 +229,7 @@ struct controller_impl {
|
||||
protocol_feature_manager protocol_features;
|
||||
controller::config conf;
|
||||
const chain_id_type chain_id; // read by thread_pool threads, value will not be changed
|
||||
bool replaying = false;
|
||||
std::optional<fc::time_point> replay_head_time;
|
||||
db_read_mode read_mode = db_read_mode::SPECULATIVE;
|
||||
bool in_trx_requiring_checks = false; ///< if true, checks that are normally skipped on replay (e.g. auth checks) cannot be skipped
|
||||
std::optional<fc::microseconds> subjective_cpu_leeway;
|
||||
@@ -483,7 +482,8 @@ struct controller_impl {
|
||||
}
|
||||
|
||||
auto blog_head = blog.head();
|
||||
replaying = true;
|
||||
auto blog_head_time = blog_head ? blog_head->timestamp.to_time_point() : fork_db.root()->header.timestamp.to_time_point();
|
||||
replay_head_time = blog_head_time;
|
||||
auto start_block_num = head->block_num + 1;
|
||||
auto start = fc::time_point::now();
|
||||
|
||||
@@ -551,7 +551,7 @@ struct controller_impl {
|
||||
ilog( "replayed ${n} blocks in ${duration} seconds, ${mspb} ms/block",
|
||||
("n", head->block_num + 1 - start_block_num)("duration", (end-start).count()/1000000)
|
||||
("mspb", ((end-start).count()/1000.0)/(head->block_num-start_block_num)) );
|
||||
replaying = false;
|
||||
replay_head_time.reset();
|
||||
|
||||
if( except_ptr ) {
|
||||
std::rethrow_exception( except_ptr );
|
||||
@@ -820,10 +820,7 @@ struct controller_impl {
|
||||
});
|
||||
}
|
||||
|
||||
void add_to_snapshot( const snapshot_writer_ptr& snapshot ) {
|
||||
// clear in case the previous call to clear did not finish in time of deadline
|
||||
clear_expired_input_transactions( fc::time_point::maximum() );
|
||||
|
||||
void add_to_snapshot( const snapshot_writer_ptr& snapshot ) const {
|
||||
snapshot->write_section<chain_snapshot_header>([this]( auto §ion ){
|
||||
section.add_row(chain_snapshot_header(), db);
|
||||
});
|
||||
@@ -996,7 +993,7 @@ struct controller_impl {
|
||||
);
|
||||
}
|
||||
|
||||
sha256 calculate_integrity_hash() {
|
||||
sha256 calculate_integrity_hash() const {
|
||||
sha256::encoder enc;
|
||||
auto hash_writer = std::make_shared<integrity_hash_snapshot_writer>(enc);
|
||||
add_to_snapshot(hash_writer);
|
||||
@@ -1255,7 +1252,6 @@ struct controller_impl {
|
||||
uint32_t billed_cpu_time_us, bool explicit_billed_cpu_time = false )
|
||||
{ try {
|
||||
|
||||
auto start = fc::time_point::now();
|
||||
const bool validating = !self.is_producing_block();
|
||||
EOS_ASSERT( !validating || explicit_billed_cpu_time, transaction_exception, "validating requires explicit billing" );
|
||||
|
||||
@@ -1295,10 +1291,6 @@ struct controller_impl {
|
||||
trace->scheduled = true;
|
||||
trace->receipt = push_receipt( gtrx.trx_id, transaction_receipt::expired, billed_cpu_time_us, 0 ); // expire the transaction
|
||||
trace->account_ram_delta = account_delta( gtrx.payer, trx_removal_ram_delta );
|
||||
trace->elapsed = fc::time_point::now() - start;
|
||||
pending->_block_report.total_cpu_usage_us += billed_cpu_time_us;
|
||||
pending->_block_report.total_elapsed_time += trace->elapsed;
|
||||
pending->_block_report.total_time += trace->elapsed;
|
||||
emit( self.accepted_transaction, trx );
|
||||
dmlog_applied_transaction(trace);
|
||||
emit( self.applied_transaction, std::tie(trace, trx->packed_trx()) );
|
||||
@@ -1329,7 +1321,7 @@ struct controller_impl {
|
||||
trace->error_code = controller::convert_exception_to_error_code( e );
|
||||
trace->except = e;
|
||||
trace->except_ptr = std::current_exception();
|
||||
trace->elapsed = fc::time_point::now() - start;
|
||||
trace->elapsed = fc::time_point::now() - trx_context.start;
|
||||
|
||||
if (auto dm_logger = get_deep_mind_logger()) {
|
||||
dm_logger->on_fail_deferred();
|
||||
@@ -1373,11 +1365,6 @@ struct controller_impl {
|
||||
|
||||
restore.cancel();
|
||||
|
||||
pending->_block_report.total_net_usage += trace->net_usage;
|
||||
pending->_block_report.total_cpu_usage_us += trace->receipt->cpu_usage_us;
|
||||
pending->_block_report.total_elapsed_time += trace->elapsed;
|
||||
pending->_block_report.total_time += fc::time_point::now() - start;
|
||||
|
||||
return trace;
|
||||
} catch( const disallowed_transaction_extensions_bad_block_exception& ) {
|
||||
throw;
|
||||
@@ -1408,18 +1395,13 @@ struct controller_impl {
|
||||
trace = error_trace;
|
||||
if( !trace->except_ptr ) {
|
||||
trace->account_ram_delta = account_delta( gtrx.payer, trx_removal_ram_delta );
|
||||
trace->elapsed = fc::time_point::now() - start;
|
||||
emit( self.accepted_transaction, trx );
|
||||
dmlog_applied_transaction(trace);
|
||||
emit( self.applied_transaction, std::tie(trace, trx->packed_trx()) );
|
||||
undo_session.squash();
|
||||
pending->_block_report.total_net_usage += trace->net_usage;
|
||||
if( trace->receipt ) pending->_block_report.total_cpu_usage_us += trace->receipt->cpu_usage_us;
|
||||
pending->_block_report.total_elapsed_time += trace->elapsed;
|
||||
pending->_block_report.total_time += trace->elapsed;
|
||||
return trace;
|
||||
}
|
||||
trace->elapsed = fc::time_point::now() - start;
|
||||
trace->elapsed = fc::time_point::now() - trx_context.start;
|
||||
}
|
||||
|
||||
// Only subjective OR hard failure logic below:
|
||||
@@ -1466,11 +1448,6 @@ struct controller_impl {
|
||||
emit( self.applied_transaction, std::tie(trace, trx->packed_trx()) );
|
||||
}
|
||||
|
||||
pending->_block_report.total_net_usage += trace->net_usage;
|
||||
if( trace->receipt ) pending->_block_report.total_cpu_usage_us += trace->receipt->cpu_usage_us;
|
||||
pending->_block_report.total_elapsed_time += trace->elapsed;
|
||||
pending->_block_report.total_time += fc::time_point::now() - start;
|
||||
|
||||
return trace;
|
||||
} FC_CAPTURE_AND_RETHROW() } /// push_scheduled_transaction
|
||||
|
||||
@@ -1551,8 +1528,10 @@ struct controller_impl {
|
||||
trx_context.init_for_implicit_trx();
|
||||
trx_context.enforce_whiteblacklist = false;
|
||||
} else {
|
||||
bool skip_recording = replay_head_time && (time_point(trn.expiration) < *replay_head_time);
|
||||
trx_context.init_for_input_trx( trx->packed_trx()->get_unprunable_size(),
|
||||
trx->packed_trx()->get_prunable_size() );
|
||||
trx->packed_trx()->get_prunable_size(),
|
||||
skip_recording);
|
||||
}
|
||||
|
||||
trx_context.delay = fc::seconds(trn.delay_sec);
|
||||
@@ -1611,13 +1590,6 @@ struct controller_impl {
|
||||
trx_context.squash();
|
||||
}
|
||||
|
||||
if( !trx->read_only ) {
|
||||
pending->_block_report.total_net_usage += trace->net_usage;
|
||||
pending->_block_report.total_cpu_usage_us += trace->receipt->cpu_usage_us;
|
||||
pending->_block_report.total_elapsed_time += trace->elapsed;
|
||||
pending->_block_report.total_time += fc::time_point::now() - start;
|
||||
}
|
||||
|
||||
return trace;
|
||||
} catch( const disallowed_transaction_extensions_bad_block_exception& ) {
|
||||
throw;
|
||||
@@ -1635,14 +1607,9 @@ struct controller_impl {
|
||||
}
|
||||
|
||||
if (!trx->read_only) {
|
||||
emit(self.accepted_transaction, trx);
|
||||
dmlog_applied_transaction(trace);
|
||||
emit(self.applied_transaction, std::tie(trace, trx->packed_trx()));
|
||||
|
||||
pending->_block_report.total_net_usage += trace->net_usage;
|
||||
if( trace->receipt ) pending->_block_report.total_cpu_usage_us += trace->receipt->cpu_usage_us;
|
||||
pending->_block_report.total_elapsed_time += trace->elapsed;
|
||||
pending->_block_report.total_time += fc::time_point::now() - start;
|
||||
emit(self.accepted_transaction, trx);
|
||||
dmlog_applied_transaction(trace);
|
||||
emit(self.applied_transaction, std::tie(trace, trx->packed_trx()));
|
||||
}
|
||||
|
||||
return trace;
|
||||
@@ -1762,7 +1729,7 @@ struct controller_impl {
|
||||
)
|
||||
{
|
||||
// Promote proposed schedule to pending schedule.
|
||||
if( !replaying ) {
|
||||
if( !replay_head_time ) {
|
||||
ilog( "promoting proposed schedule (set in block ${proposed_num}) to pending; current block: ${n} lib: ${lib} schedule: ${schedule} ",
|
||||
("proposed_num", *gpo.proposed_schedule_block_num)("n", pbhs.block_num)
|
||||
("lib", pbhs.dpos_irreversible_blocknum)
|
||||
@@ -2096,6 +2063,12 @@ struct controller_impl {
|
||||
EOS_ASSERT( r == static_cast<const transaction_receipt_header&>(receipt),
|
||||
block_validate_exception, "receipt does not match, ${lhs} != ${rhs}",
|
||||
("lhs", r)("rhs", static_cast<const transaction_receipt_header&>(receipt)) );
|
||||
|
||||
if( trace ) {
|
||||
br.total_net_usage += trace->net_usage;
|
||||
if( trace->receipt ) br.total_cpu_usage_us += trace->receipt->cpu_usage_us;
|
||||
br.total_elapsed_time += trace->elapsed;
|
||||
}
|
||||
}
|
||||
|
||||
finalize_block();
|
||||
@@ -2116,7 +2089,6 @@ struct controller_impl {
|
||||
// create completed_block with the existing block_state as we just verified it is the same as assembled_block
|
||||
pending->_block_stage = completed_block{ bsp };
|
||||
|
||||
br = pending->_block_report; // copy before commit block destroys pending
|
||||
commit_block(false);
|
||||
br.total_time = fc::time_point::now() - start;
|
||||
return;
|
||||
@@ -2422,7 +2394,7 @@ struct controller_impl {
|
||||
//Look for expired transactions in the deduplication list, and remove them.
|
||||
auto& transaction_idx = db.get_mutable_index<transaction_multi_index>();
|
||||
const auto& dedupe_index = transaction_idx.indices().get<by_expiration>();
|
||||
auto now = self.is_building_block() ? self.pending_block_time() : self.head_block_time();
|
||||
auto now = self.pending_block_time();
|
||||
const auto total = dedupe_index.size();
|
||||
uint32_t num_removed = 0;
|
||||
while( (!dedupe_index.empty()) && ( now > fc::time_point(dedupe_index.begin()->expiration) ) ) {
|
||||
@@ -2857,7 +2829,7 @@ void controller::start_block( block_timestamp_type when,
|
||||
block_status::incomplete, std::optional<block_id_type>(), deadline );
|
||||
}
|
||||
|
||||
block_state_ptr controller::finalize_block( block_report& br, const signer_callback_type& signer_callback ) {
|
||||
block_state_ptr controller::finalize_block( const signer_callback_type& signer_callback ) {
|
||||
validate_db_available_size();
|
||||
|
||||
my->finalize_block();
|
||||
@@ -2878,8 +2850,6 @@ block_state_ptr controller::finalize_block( block_report& br, const signer_callb
|
||||
|
||||
my->pending->_block_stage = completed_block{ bsp };
|
||||
|
||||
br = my->pending->_block_report;
|
||||
|
||||
return bsp;
|
||||
}
|
||||
|
||||
@@ -3134,11 +3104,11 @@ block_id_type controller::get_block_id_for_num( uint32_t block_num )const { try
|
||||
return id;
|
||||
} FC_CAPTURE_AND_RETHROW( (block_num) ) }
|
||||
|
||||
sha256 controller::calculate_integrity_hash() { try {
|
||||
sha256 controller::calculate_integrity_hash()const { try {
|
||||
return my->calculate_integrity_hash();
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
void controller::write_snapshot( const snapshot_writer_ptr& snapshot ) {
|
||||
void controller::write_snapshot( const snapshot_writer_ptr& snapshot ) const {
|
||||
EOS_ASSERT( !my->pending, block_validate_exception, "cannot take a consistent snapshot with a pending block" );
|
||||
return my->add_to_snapshot(snapshot);
|
||||
}
|
||||
|
||||
@@ -164,19 +164,18 @@ namespace eosio { namespace chain {
|
||||
fc::time_point block_deadline, fc::microseconds max_transaction_time,
|
||||
uint32_t billed_cpu_time_us, bool explicit_billed_cpu_time );
|
||||
|
||||
block_state_ptr finalize_block( const signer_callback_type& signer_callback );
|
||||
void sign_block( const signer_callback_type& signer_callback );
|
||||
void commit_block();
|
||||
|
||||
std::future<block_state_ptr> create_block_state_future( const block_id_type& id, const signed_block_ptr& b );
|
||||
|
||||
struct block_report {
|
||||
size_t total_net_usage = 0;
|
||||
size_t total_cpu_usage_us = 0;
|
||||
fc::microseconds total_elapsed_time{};
|
||||
fc::microseconds total_time{};
|
||||
};
|
||||
|
||||
block_state_ptr finalize_block( block_report& br, const signer_callback_type& signer_callback );
|
||||
void sign_block( const signer_callback_type& signer_callback );
|
||||
void commit_block();
|
||||
|
||||
std::future<block_state_ptr> create_block_state_future( const block_id_type& id, const signed_block_ptr& b );
|
||||
|
||||
/**
|
||||
* @param br returns statistics for block
|
||||
* @param block_state_future provide from call to create_block_state_future
|
||||
@@ -257,8 +256,8 @@ namespace eosio { namespace chain {
|
||||
|
||||
block_id_type get_block_id_for_num( uint32_t block_num )const;
|
||||
|
||||
sha256 calculate_integrity_hash();
|
||||
void write_snapshot( const snapshot_writer_ptr& snapshot );
|
||||
sha256 calculate_integrity_hash()const;
|
||||
void write_snapshot( const snapshot_writer_ptr& snapshot )const;
|
||||
|
||||
bool sender_avoids_whitelist_blacklist_enforcement( account_name sender )const;
|
||||
void check_actor_list( const flat_set<account_name>& actors )const;
|
||||
|
||||
@@ -45,7 +45,8 @@ namespace eosio { namespace chain {
|
||||
void init_for_implicit_trx( uint64_t initial_net_usage = 0 );
|
||||
|
||||
void init_for_input_trx( uint64_t packed_trx_unprunable_size,
|
||||
uint64_t packed_trx_prunable_size );
|
||||
uint64_t packed_trx_prunable_size,
|
||||
bool skip_recording);
|
||||
|
||||
void init_for_deferred_trx( fc::time_point published );
|
||||
|
||||
|
||||
@@ -234,7 +234,8 @@ namespace eosio { namespace chain {
|
||||
}
|
||||
|
||||
void transaction_context::init_for_input_trx( uint64_t packed_trx_unprunable_size,
|
||||
uint64_t packed_trx_prunable_size )
|
||||
uint64_t packed_trx_prunable_size,
|
||||
bool skip_recording )
|
||||
{
|
||||
const transaction& trx = packed_trx.get_transaction();
|
||||
if( trx.transaction_extensions.size() > 0 ) {
|
||||
@@ -271,7 +272,8 @@ namespace eosio { namespace chain {
|
||||
validate_referenced_accounts( trx, enforce_whiteblacklist && control.is_producing_block() );
|
||||
}
|
||||
init( initial_net_usage);
|
||||
record_transaction( packed_trx.id(), trx.expiration ); /// checks for dupes
|
||||
if (!skip_recording)
|
||||
record_transaction( packed_trx.id(), trx.expiration ); /// checks for dupes
|
||||
}
|
||||
|
||||
void transaction_context::init_for_deferred_trx( fc::time_point p )
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// https://github.com/CLIUtils/CLI11
|
||||
//
|
||||
// This is a standalone header file generated by MakeSingleHeader.py in CLI11/scripts
|
||||
// from: b19d133
|
||||
// from: 1d3b0a7
|
||||
//
|
||||
// CLI11 2.2.0 Copyright (c) 2017-2022 University of Cincinnati, developed by Henry
|
||||
// Schreiner under NSF AWARD 1414736. All rights reserved.
|
||||
@@ -34,28 +34,28 @@
|
||||
#pragma once
|
||||
|
||||
// Standard combined includes:
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <exception>
|
||||
#include <map>
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
#include <type_traits>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
#include <locale>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <iomanip>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <exception>
|
||||
#include <cstdint>
|
||||
#include <cmath>
|
||||
#include <numeric>
|
||||
#include <tuple>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <set>
|
||||
#include <iomanip>
|
||||
#include <locale>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
#define CLI11_VERSION_MAJOR 2
|
||||
@@ -9420,134 +9420,4 @@ inline std::string Formatter::make_option_usage(const Option *opt) const {
|
||||
|
||||
|
||||
|
||||
|
||||
class LeapFormatter : public Formatter {
|
||||
// pseudographics - to draw subcommand tree
|
||||
const char* tree_line = u8"\u2502";
|
||||
const char* tree_angle = u8"\u2514";
|
||||
const char* tree_fork = u8"\u251C";
|
||||
|
||||
public:
|
||||
LeapFormatter() : Formatter() {
|
||||
// this gives better, more compact display
|
||||
column_width(25);
|
||||
}
|
||||
LeapFormatter(const LeapFormatter&) = default;
|
||||
LeapFormatter(LeapFormatter&&) = default;
|
||||
|
||||
/// This prints out all the subcommands
|
||||
virtual std::string make_subcommands(const App* app, AppFormatMode mode) const {
|
||||
std::stringstream out;
|
||||
|
||||
std::vector<const App*> subcommands = app->get_subcommands({});
|
||||
|
||||
// Make a list in definition order of the groups seen
|
||||
std::vector<std::string> subcmd_groups_seen;
|
||||
for(const App* com: subcommands) {
|
||||
if(com->get_name().empty()) {
|
||||
if(!com->get_group().empty()) {
|
||||
out << make_expanded(com);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
std::string group_key = com->get_group();
|
||||
if(!group_key.empty() &&
|
||||
std::find_if(subcmd_groups_seen.begin(), subcmd_groups_seen.end(), [&group_key](std::string a) {
|
||||
return detail::to_lower(a) == detail::to_lower(group_key);
|
||||
}) == subcmd_groups_seen.end())
|
||||
subcmd_groups_seen.push_back(group_key);
|
||||
}
|
||||
|
||||
// For each group, filter out and print subcommands
|
||||
for(const std::string& group: subcmd_groups_seen) {
|
||||
if(mode != AppFormatMode::SubCompact) {// do not show "Subcommands" header for nested tems in compact mode
|
||||
out << "\n"
|
||||
<< group << ":\n";
|
||||
}
|
||||
std::vector<const App*> subcommands_group = app->get_subcommands([&group](const App* sub_app) {
|
||||
return detail::to_lower(sub_app->get_group()) == detail::to_lower(group);
|
||||
});
|
||||
for(const App* new_com: subcommands_group) {
|
||||
if(new_com->get_name().empty())
|
||||
continue;
|
||||
|
||||
std::string tree_symbol = (subcommands_group.back() == new_com ? tree_angle : tree_fork);
|
||||
std::string line_symbol = (subcommands_group.back() == new_com ? "" : tree_line);
|
||||
std::string subc_symbol = "";
|
||||
|
||||
const App* parent = app->get_parent();
|
||||
if(parent != nullptr) {
|
||||
std::vector<const App*> sc_group = parent->get_subcommands([&group](const App* sub_app) {
|
||||
return detail::to_lower(sub_app->get_group()) == detail::to_lower(group);
|
||||
});
|
||||
if(sc_group.back() != app) {
|
||||
subc_symbol = tree_line;
|
||||
}
|
||||
}
|
||||
|
||||
switch(mode) {
|
||||
case AppFormatMode::All:
|
||||
out << tree_symbol << new_com->help(new_com->get_name(), AppFormatMode::Sub);
|
||||
out << "\n";
|
||||
break;
|
||||
case AppFormatMode::AllCompact:
|
||||
|
||||
out << tree_symbol << new_com->help(new_com->get_name(), AppFormatMode::SubCompact);
|
||||
out << line_symbol;
|
||||
out << "\n";
|
||||
break;
|
||||
case AppFormatMode::Normal:
|
||||
case AppFormatMode::Sub:
|
||||
out << make_subcommand(new_com);
|
||||
break;
|
||||
case AppFormatMode::SubCompact:
|
||||
out << tree_symbol << make_expanded(new_com, mode);
|
||||
break;
|
||||
default:
|
||||
throw HorribleError("Internal error: unknown help type requested");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return out.str();
|
||||
}
|
||||
|
||||
/// This prints out a subcommand in help-all
|
||||
virtual std::string make_expanded(const App* sub, AppFormatMode mode = AppFormatMode::Sub) const {
|
||||
std::stringstream out;
|
||||
std::string tmp;
|
||||
std::string subc_symbol = " ";
|
||||
if(mode == AppFormatMode::SubCompact) {
|
||||
detail::format_help(out, sub->get_display_name(true), sub->get_description(), column_width_);
|
||||
out << make_subcommands(sub, mode);
|
||||
} else {
|
||||
out << sub->get_display_name(true) << "\n";
|
||||
out << make_description(sub);
|
||||
if(sub->get_name().empty() && !sub->get_aliases().empty()) {
|
||||
detail::format_aliases(out, sub->get_aliases(), column_width_ + 2);
|
||||
}
|
||||
out << make_positionals(sub);
|
||||
out << make_groups(sub, mode);
|
||||
out << make_subcommands(sub, mode);
|
||||
}
|
||||
|
||||
// Drop blank spaces
|
||||
tmp = detail::find_and_replace(out.str(), "\n\n", "\n");
|
||||
tmp = tmp.substr(0, tmp.size() - 1);// Remove the final '\n'
|
||||
|
||||
//
|
||||
auto group = sub->get_parent()->get_group();
|
||||
std::vector<const App*> sc_group = sub->get_parent()->get_subcommands(
|
||||
[&group](const App* sub_app) { return detail::to_lower(sub_app->get_group()) == detail::to_lower(group); });
|
||||
|
||||
if(sc_group.back() != sub) {
|
||||
subc_symbol = tree_line;
|
||||
}
|
||||
|
||||
// Indent all but the first line (the name)
|
||||
return detail::find_and_replace(tmp, "\n", "\n" + subc_symbol + " ") + "\n";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace CLI
|
||||
|
||||
+1
-1
Submodule libraries/eos-vm updated: 8345005a9d...7db4b33fa9
@@ -29,9 +29,9 @@ target_include_directories(secp256k1
|
||||
target_link_libraries(secp256k1 PRIVATE secp256k1-internal)
|
||||
|
||||
install( TARGETS secp256k1
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} COMPONENT dev EXCLUDE_FROM_ALL
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} COMPONENT dev EXCLUDE_FROM_ALL
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} COMPONENT dev EXCLUDE_FROM_ALL
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} ${INSTALL_COMPONENT_ARGS}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} ${INSTALL_COMPONENT_ARGS}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} ${INSTALL_COMPONENT_ARGS}
|
||||
)
|
||||
|
||||
add_executable(secp256k1-bench secp256k1/src/bench.c)
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
add_library(prometheus-core
|
||||
prometheus-cpp/core/src/check_names.cc
|
||||
prometheus-cpp/core/src/counter.cc
|
||||
prometheus-cpp/core/src/detail/builder.cc
|
||||
prometheus-cpp/core/src/detail/ckms_quantiles.cc
|
||||
prometheus-cpp/core/src/detail/time_window_quantiles.cc
|
||||
prometheus-cpp/core/src/detail/utils.cc
|
||||
prometheus-cpp/core/src/family.cc
|
||||
prometheus-cpp/core/src/gauge.cc
|
||||
prometheus-cpp/core/src/histogram.cc
|
||||
prometheus-cpp/core/src/info.cc
|
||||
prometheus-cpp/core/src/registry.cc
|
||||
prometheus-cpp/core/src/serializer.cc
|
||||
prometheus-cpp/core/src/summary.cc
|
||||
prometheus-cpp/core/src/text_serializer.cc
|
||||
)
|
||||
|
||||
target_include_directories( prometheus-core PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/prometheus-cpp/core/include)
|
||||
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
# define PROMETHEUS_CPP_CORE_EXPORT
|
||||
# define PROMETHEUS_CPP_CORE_NO_EXPORT
|
||||
@@ -0,0 +1 @@
|
||||
3rdparty
|
||||
@@ -0,0 +1,10 @@
|
||||
build:asan --strip=never
|
||||
build:asan --copt -fsanitize=address
|
||||
build:asan --copt -DADDRESS_SANITIZER
|
||||
build:asan --copt -O0
|
||||
build:asan --copt -fno-omit-frame-pointer
|
||||
build:asan --copt -g
|
||||
build:asan --linkopt -fsanitize=address
|
||||
build:asan --cc_output_directory_tag=asan
|
||||
|
||||
build:ssl --define=with_civetweb_ssl=true
|
||||
@@ -0,0 +1,2 @@
|
||||
BasedOnStyle: Google
|
||||
DerivePointerAlignment: false
|
||||
@@ -0,0 +1,61 @@
|
||||
name: Bazel CI
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Bazel on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-latest, windows-latest]
|
||||
include:
|
||||
- os: macOS-latest
|
||||
bazel_args: "--cxxopt=-std=c++14"
|
||||
- os: ubuntu-latest
|
||||
bazel_args: "--cxxopt=-std=c++14"
|
||||
- os: windows-latest
|
||||
bazel_args: "--cxxopt=/std:c++14"
|
||||
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- 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 with SSL
|
||||
run: bazel build --config=ssl ${{ matrix.bazel_args }} //...
|
||||
|
||||
- name: Test with SSL
|
||||
run: bazel test --config=ssl ${{ matrix.bazel_args }} --test_output=all //...
|
||||
|
||||
- name: Build
|
||||
run: bazel build ${{ matrix.bazel_args }} //...
|
||||
|
||||
- name: Test
|
||||
run: bazel test ${{ matrix.bazel_args }} --test_output=all //...
|
||||
|
||||
- name: Scraping Test
|
||||
if: runner.os != 'Windows'
|
||||
run: bazel test ${{ matrix.bazel_args }} --test_output=all //pull/tests/integration:scrape-test
|
||||
|
||||
- name: Benchmark
|
||||
run: bazel run ${{ matrix.bazel_args }} -c opt //core/benchmarks
|
||||
@@ -0,0 +1,131 @@
|
||||
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-2019]
|
||||
dependencies: [submodule, vcpkg]
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: ${{ matrix.dependencies == 'submodule' }}
|
||||
|
||||
- name: Mount vcpkg cache
|
||||
if: matrix.dependencies == 'vcpkg'
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: "~/.cache/vcpkg/archives"
|
||||
key: vcpkg-${{ matrix.os }}
|
||||
|
||||
- name: Default to x64-windows vcpkg triplet
|
||||
if: matrix.dependencies == 'vcpkg' && runner.os == 'Windows'
|
||||
run: echo "VCPKG_DEFAULT_TRIPLET=x64-windows" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
|
||||
|
||||
- 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 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"
|
||||
run: cmake --install ${{ github.workspace }}/_build --config Debug
|
||||
|
||||
- name: "Install Release"
|
||||
run: cmake --install ${{ github.workspace }}/_build --config Release
|
||||
|
||||
- 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-cmake -B ${{ github.workspace }}/_import_cmake
|
||||
|
||||
- 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-cmake -B ${{ github.workspace }}/_import_cmake
|
||||
|
||||
- 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-cmake -B ${{ github.workspace }}/_import_cmake
|
||||
|
||||
- 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-cmake -B ${{ github.workspace }}/_import_cmake
|
||||
|
||||
- name: "Build CMake import Debug"
|
||||
run: cmake --build ${{ github.workspace }}/_import_cmake --config Debug
|
||||
|
||||
- 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
|
||||
@@ -0,0 +1,60 @@
|
||||
name: Coverage
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Code Coverage
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Mount vcpkg cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: "~/.cache/vcpkg/archives"
|
||||
key: vcpkg-${{ runner.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 lcov
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt-get install -y lcov
|
||||
|
||||
- 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: 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
|
||||
@@ -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@v3
|
||||
|
||||
- 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
|
||||
@@ -0,0 +1,55 @@
|
||||
name: Linting
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
iwyu:
|
||||
name: Include What You Use
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: debian:sid-slim
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get install -y --no-install-recommends ca-certificates clang-14 cmake git iwyu libbenchmark-dev libcurl4-openssl-dev ninja-build zlib1g-dev
|
||||
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: "CMake Configure"
|
||||
run: cmake -GNinja -DRUN_IWYU=ON -DCMAKE_C_COMPILER=clang-14 -DCMAKE_CXX_COMPILER=clang++-14 -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
|
||||
|
||||
format:
|
||||
name: Clang Format
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# clang-format comes pre-installed
|
||||
# https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-Readme.md
|
||||
#- 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-12
|
||||
|
||||
- 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-12 -style=file -i {} \;
|
||||
|
||||
- name: Check for changes
|
||||
run: git diff --exit-code
|
||||
@@ -0,0 +1,34 @@
|
||||
on:
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
name: Handle Release
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Upload Release Asset
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: true
|
||||
|
||||
- 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
|
||||
@@ -0,0 +1,7 @@
|
||||
/bazel-*
|
||||
cmake-build-*/
|
||||
_*/
|
||||
.idea/
|
||||
doc/html/
|
||||
.vscode
|
||||
build
|
||||
@@ -0,0 +1,6 @@
|
||||
[submodule "googletest"]
|
||||
path = 3rdparty/googletest
|
||||
url = https://github.com/google/googletest.git
|
||||
[submodule "civetweb"]
|
||||
path = 3rdparty/civetweb
|
||||
url = https://github.com/civetweb/civetweb.git
|
||||
@@ -0,0 +1,11 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
config_setting(
|
||||
name = "windows",
|
||||
values = {"cpu": "x64_windows"},
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "windows_msvc",
|
||||
values = {"cpu": "x64_windows_msvc"},
|
||||
)
|
||||
@@ -0,0 +1,193 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
|
||||
if(POLICY CMP0091)
|
||||
cmake_policy(SET CMP0091 NEW) # recognize CMAKE_MSVC_RUNTIME_LIBRARY
|
||||
endif()
|
||||
|
||||
project(prometheus-cpp
|
||||
VERSION 1.1.0
|
||||
DESCRIPTION "Prometheus Client Library for Modern C++"
|
||||
HOMEPAGE_URL "https://github.com/jupp0r/prometheus-cpp"
|
||||
)
|
||||
|
||||
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)
|
||||
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)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_EXTENSIONS Off)
|
||||
endif()
|
||||
|
||||
# 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
|
||||
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)
|
||||
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)
|
||||
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
|
||||
set(CMAKE_VISIBILITY_INLINES_HIDDEN YES)
|
||||
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)
|
||||
|
||||
if(ENABLE_TESTING)
|
||||
if(USE_THIRDPARTY_LIBRARIES)
|
||||
find_package(googlemock-3rdparty CONFIG REQUIRED)
|
||||
else()
|
||||
find_package(GTest 1.8.1 CONFIG REQUIRED)
|
||||
endif()
|
||||
find_package(benchmark CONFIG)
|
||||
enable_testing()
|
||||
endif()
|
||||
|
||||
# build flags for CI system
|
||||
|
||||
if(ENABLE_WARNINGS_AS_ERRORS AND NOT MSVC)
|
||||
add_compile_options(
|
||||
$<$<AND:$<STREQUAL:$<COMPILE_LANGUAGE>,CXX>,$<CXX_COMPILER_ID:AppleClang>>:-Werror>
|
||||
$<$<AND:$<STREQUAL:$<COMPILE_LANGUAGE>,CXX>,$<CXX_COMPILER_ID:AppleClang>>:-Wall>
|
||||
$<$<AND:$<STREQUAL:$<COMPILE_LANGUAGE>,CXX>,$<CXX_COMPILER_ID:AppleClang>>:-Wextra>
|
||||
$<$<AND:$<STREQUAL:$<COMPILE_LANGUAGE>,CXX>,$<CXX_COMPILER_ID:AppleClang>>:-pedantic-errors>
|
||||
$<$<AND:$<STREQUAL:$<COMPILE_LANGUAGE>,CXX>,$<CXX_COMPILER_ID:GNU>>:-Werror>
|
||||
$<$<AND:$<STREQUAL:$<COMPILE_LANGUAGE>,CXX>,$<CXX_COMPILER_ID:GNU>>:-Wall>
|
||||
$<$<AND:$<STREQUAL:$<COMPILE_LANGUAGE>,CXX>,$<CXX_COMPILER_ID:GNU>>:-pedantic-errors>
|
||||
)
|
||||
endif()
|
||||
|
||||
# pkgconfig
|
||||
|
||||
if(GENERATE_PKGCONFIG)
|
||||
# see https://github.com/jupp0r/prometheus-cpp/issues/587
|
||||
if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
set(PROMETHEUS_CPP_PKGCONFIG_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
else()
|
||||
set(PROMETHEUS_CPP_PKGCONFIG_INCLUDEDIR "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
endif()
|
||||
|
||||
if(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}")
|
||||
set(PROMETHEUS_CPP_PKGCONFIG_LIBDIR "${CMAKE_INSTALL_LIBDIR}")
|
||||
else()
|
||||
set(PROMETHEUS_CPP_PKGCONFIG_LIBDIR "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# prometheus-cpp
|
||||
|
||||
add_subdirectory(core)
|
||||
|
||||
if(ENABLE_PULL)
|
||||
add_subdirectory(pull)
|
||||
endif()
|
||||
|
||||
if(ENABLE_PUSH)
|
||||
add_subdirectory(push)
|
||||
endif()
|
||||
|
||||
# install
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
install(
|
||||
EXPORT ${PROJECT_NAME}-targets
|
||||
NAMESPACE ${PROJECT_NAME}::
|
||||
FILE ${PROJECT_NAME}-targets.cmake
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
|
||||
)
|
||||
|
||||
configure_package_config_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/${PROJECT_NAME}-config.cmake.in"
|
||||
${PROJECT_NAME}-config.cmake
|
||||
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
|
||||
NO_CHECK_REQUIRED_COMPONENTS_MACRO
|
||||
PATH_VARS CMAKE_INSTALL_INCLUDEDIR
|
||||
)
|
||||
|
||||
install(
|
||||
FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake"
|
||||
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 "${PROJECT_DESCRIPTION}")
|
||||
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_GENERATE_SHLIBS ON)
|
||||
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)
|
||||
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)
|
||||
@@ -0,0 +1,25 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016-2021 Jupp Mueller
|
||||
Copyright (c) 2017-2022 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
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,382 @@
|
||||
# Prometheus Client Library for Modern C++
|
||||
|
||||
[](https://github.com/jupp0r/prometheus-cpp/actions?workflow=Continuous+Integration)
|
||||
[](https://travis-ci.org/jupp0r/prometheus-cpp)
|
||||
[](https://coveralls.io/github/jupp0r/prometheus-cpp?branch=master)
|
||||
[](https://scan.coverity.com/projects/jupp0r-prometheus-cpp)
|
||||
|
||||
This library aims to enable
|
||||
[Metrics-Driven Development](https://sookocheff.com/post/mdd/mdd/) for
|
||||
C++ services. It implements the
|
||||
[Prometheus Data Model](https://prometheus.io/docs/concepts/data_model/),
|
||||
a powerful abstraction on which to collect and expose metrics. We
|
||||
offer the possibility for metrics to be collected by Prometheus, but
|
||||
other push/pull collections can be added as plugins.
|
||||
|
||||
## Usage
|
||||
|
||||
See https://jupp0r.github.io/prometheus-cpp for more detailed interface documentation.
|
||||
|
||||
``` c++
|
||||
#include <prometheus/counter.h>
|
||||
#include <prometheus/exposer.h>
|
||||
#include <prometheus/registry.h>
|
||||
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
int main() {
|
||||
using namespace prometheus;
|
||||
|
||||
// create an http server running on port 8080
|
||||
Exposer exposer{"127.0.0.1:8080"};
|
||||
|
||||
// create a metrics registry
|
||||
// @note it's the users responsibility to keep the object alive
|
||||
auto registry = std::make_shared<Registry>();
|
||||
|
||||
// add a new counter family to the registry (families combine values with the
|
||||
// same name, but distinct label dimensions)
|
||||
//
|
||||
// @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 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));
|
||||
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<std::string, 4> methods = {"GET", "PUT", "POST", "HEAD"};
|
||||
auto method = methods.at(random_value % methods.size());
|
||||
// dynamically calling Family<T>.Add() works but is slow and should be
|
||||
// avoided
|
||||
http_requests_counter.Add({{"method", method}}).Increment();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
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
|
||||
|
||||
There are two supported ways to build
|
||||
`prometheus-cpp` - [CMake](https://cmake.org)
|
||||
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 [GitHub Workflows](.github/workflows) might help.
|
||||
|
||||
### via CMake
|
||||
|
||||
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
|
||||
git submodule init
|
||||
git submodule update
|
||||
|
||||
mkdir _build
|
||||
cd _build
|
||||
|
||||
# run cmake
|
||||
cmake .. -DBUILD_SHARED_LIBS=ON -DENABLE_PUSH=OFF -DENABLE_COMPRESSION=OFF
|
||||
|
||||
# build
|
||||
cmake --build . --parallel 4
|
||||
|
||||
# run tests
|
||||
ctest -V
|
||||
|
||||
# install the libraries and headers
|
||||
cmake --install .
|
||||
```
|
||||
|
||||
### via Bazel
|
||||
|
||||
Install [bazel](https://www.bazel.io). Bazel makes it easy to add
|
||||
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",
|
||||
urls = ["https://github.com/jupp0r/prometheus-cpp/archive/master.zip"],
|
||||
)
|
||||
|
||||
load("@com_github_jupp0r_prometheus_cpp//bazel:repositories.bzl", "prometheus_cpp_repositories")
|
||||
|
||||
prometheus_cpp_repositories()
|
||||
```
|
||||
|
||||
Then, you can reference this library in your own `BUILD` file, as
|
||||
demonstrated with the sample server included in this repository:
|
||||
|
||||
```python
|
||||
cc_binary(
|
||||
name = "sample_server",
|
||||
srcs = ["sample_server.cc"],
|
||||
deps = ["@com_github_jupp0r_prometheus_cpp//pull"],
|
||||
)
|
||||
```
|
||||
|
||||
When you call `prometheus_cpp_repositories()` in your `WORKSPACE` file,
|
||||
you load the following dependencies, if they do not exist yet, into your project:
|
||||
|
||||
* `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](bazel/repositories.bzl).
|
||||
|
||||
## Packaging
|
||||
|
||||
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 update --init
|
||||
|
||||
# run cmake
|
||||
cmake -B_build -DCPACK_GENERATOR=DEB -DBUILD_SHARED_LIBS=ON # or OFF for static libraries
|
||||
|
||||
# build and package
|
||||
cmake --build _build --target package --parallel $(nproc)
|
||||
```
|
||||
|
||||
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-cmake/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.
|
||||
|
||||
### 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
|
||||
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
|
||||
Guide](https://google.github.io/styleguide/cppguide.html). Make sure
|
||||
to clang-format your patches before opening a PR. Also make sure to
|
||||
adhere to [these commit message
|
||||
guidelines](https://chris.beams.io/posts/git-commit/).
|
||||
|
||||
You can check out this repo and build the library using
|
||||
``` bash
|
||||
bazel build //... # build everything
|
||||
bazel build //core //pull # build just the libraries
|
||||
```
|
||||
|
||||
Run the unit tests using
|
||||
```
|
||||
bazel test //...
|
||||
```
|
||||
|
||||
There is also an integration test that
|
||||
uses [telegraf](https://github.com/influxdata/telegraf) to scrape a
|
||||
sample server. With telegraf installed, it can be run using
|
||||
```
|
||||
bazel test //pull/tests/integration:scrape-test
|
||||
```
|
||||
|
||||
## Benchmarks
|
||||
|
||||
There's a benchmark suite you can run:
|
||||
|
||||
```
|
||||
bazel run -c opt //core/benchmarks
|
||||
|
||||
INFO: Analysed target //core/benchmarks:benchmarks (0 packages loaded, 0 targets configured).
|
||||
INFO: Found 1 target...
|
||||
Target //core/benchmarks:benchmarks up-to-date:
|
||||
bazel-bin/core/benchmarks/benchmarks
|
||||
INFO: Elapsed time: 0.356s, Critical Path: 0.01s, Remote (0.00% of the time): [queue: 0.00%, setup: 0.00%, process: 0.00%]
|
||||
INFO: 0 processes.
|
||||
INFO: Build completed successfully, 1 total action
|
||||
INFO: Build completed successfully, 1 total action
|
||||
2018-11-30 15:13:14
|
||||
Run on (4 X 2200 MHz CPU s)
|
||||
CPU Caches:
|
||||
L1 Data 32K (x2)
|
||||
L1 Instruction 32K (x2)
|
||||
L2 Unified 262K (x2)
|
||||
L3 Unified 4194K (x1)
|
||||
-----------------------------------------------------------------------------------
|
||||
Benchmark Time CPU Iterations
|
||||
-----------------------------------------------------------------------------------
|
||||
BM_Counter_Increment 13 ns 12 ns 55616469
|
||||
BM_Counter_Collect 7 ns 7 ns 99823170
|
||||
BM_Gauge_Increment 12 ns 12 ns 51511873
|
||||
BM_Gauge_Decrement 12 ns 12 ns 56831098
|
||||
BM_Gauge_SetToCurrentTime 184 ns 183 ns 3928964
|
||||
BM_Gauge_Collect 6 ns 6 ns 117223478
|
||||
BM_Histogram_Observe/0 134 ns 124 ns 5665310
|
||||
BM_Histogram_Observe/1 122 ns 120 ns 5937185
|
||||
BM_Histogram_Observe/8 137 ns 135 ns 4652863
|
||||
BM_Histogram_Observe/64 143 ns 143 ns 4835957
|
||||
BM_Histogram_Observe/512 259 ns 257 ns 2334750
|
||||
BM_Histogram_Observe/4096 1545 ns 1393 ns 620754
|
||||
BM_Histogram_Collect/0 103 ns 102 ns 5654829
|
||||
BM_Histogram_Collect/1 100 ns 100 ns 7015153
|
||||
BM_Histogram_Collect/8 608 ns 601 ns 1149652
|
||||
BM_Histogram_Collect/64 1438 ns 1427 ns 515236
|
||||
BM_Histogram_Collect/512 5178 ns 5159 ns 114619
|
||||
BM_Histogram_Collect/4096 33527 ns 33280 ns 20785
|
||||
BM_Registry_CreateFamily 320 ns 316 ns 2021567
|
||||
BM_Registry_CreateCounter/0 128 ns 128 ns 5487140
|
||||
BM_Registry_CreateCounter/1 2066 ns 2058 ns 386002
|
||||
BM_Registry_CreateCounter/8 7672 ns 7634 ns 91328
|
||||
BM_Registry_CreateCounter/64 63270 ns 62761 ns 10780
|
||||
BM_Registry_CreateCounter/512 560714 ns 558328 ns 1176
|
||||
BM_Registry_CreateCounter/4096 18672798 ns 18383000 ns 35
|
||||
BM_Summary_Observe/0/iterations:262144 9351 ns 9305 ns 262144
|
||||
BM_Summary_Observe/1/iterations:262144 9242 ns 9169 ns 262144
|
||||
BM_Summary_Observe/8/iterations:262144 14344 ns 14195 ns 262144
|
||||
BM_Summary_Observe/64/iterations:262144 19176 ns 18950 ns 262144
|
||||
BM_Summary_Collect/0/0 31 ns 30 ns 24873766
|
||||
BM_Summary_Collect/1/0 166 ns 166 ns 4266706
|
||||
BM_Summary_Collect/8/0 1040 ns 1036 ns 660527
|
||||
BM_Summary_Collect/64/0 4529 ns 4489 ns 155600
|
||||
BM_Summary_Collect/0/1 28 ns 28 ns 24866697
|
||||
BM_Summary_Collect/1/1 190 ns 188 ns 3930354
|
||||
BM_Summary_Collect/8/1 1372 ns 1355 ns 535779
|
||||
BM_Summary_Collect/64/1 9901 ns 9822 ns 64632
|
||||
BM_Summary_Collect/0/8 29 ns 29 ns 24922651
|
||||
BM_Summary_Collect/1/8 217 ns 215 ns 3278381
|
||||
BM_Summary_Collect/8/8 2275 ns 2256 ns 282503
|
||||
BM_Summary_Collect/64/8 56790 ns 55804 ns 13878
|
||||
BM_Summary_Collect/0/64 32 ns 31 ns 22548350
|
||||
BM_Summary_Collect/1/64 395 ns 389 ns 1817073
|
||||
BM_Summary_Collect/8/64 10187 ns 10064 ns 71928
|
||||
BM_Summary_Collect/64/64 374835 ns 373560 ns 1812
|
||||
BM_Summary_Collect/0/512 28 ns 28 ns 25234228
|
||||
BM_Summary_Collect/1/512 1710 ns 1639 ns 802285
|
||||
BM_Summary_Collect/8/512 50355 ns 49335 ns 15975
|
||||
BM_Summary_Collect/64/512 2520972 ns 2493417 ns 295
|
||||
BM_Summary_Collect/0/4096 31 ns 31 ns 24059034
|
||||
BM_Summary_Collect/1/4096 2719 ns 2698 ns 286186
|
||||
BM_Summary_Collect/8/4096 121689 ns 119995 ns 5647
|
||||
BM_Summary_Collect/64/4096 5660131 ns 5587634 ns 134
|
||||
BM_Summary_Collect/0/32768 29 ns 29 ns 22217567
|
||||
BM_Summary_Collect/1/32768 4344 ns 4294 ns 138135
|
||||
BM_Summary_Collect/8/32768 331563 ns 326403 ns 2017
|
||||
BM_Summary_Collect/64/32768 16363553 ns 16038182 ns 44
|
||||
BM_Summary_Collect/0/262144 27 ns 27 ns 23923036
|
||||
BM_Summary_Collect/1/262144 10457 ns 10332 ns 67690
|
||||
BM_Summary_Collect/8/262144 930434 ns 869234 ns 792
|
||||
BM_Summary_Collect/64/262144 39217069 ns 39054846 ns 13
|
||||
BM_Summary_Observe_Common/iterations:262144 5587 ns 5557 ns 262144
|
||||
BM_Summary_Collect_Common/0 676 ns 673 ns 1054630
|
||||
BM_Summary_Collect_Common/1 709 ns 705 ns 990659
|
||||
BM_Summary_Collect_Common/8 1030 ns 1025 ns 685649
|
||||
BM_Summary_Collect_Common/64 2066 ns 2055 ns 339969
|
||||
BM_Summary_Collect_Common/512 5754 ns 5248 ns 156895
|
||||
BM_Summary_Collect_Common/4096 23894 ns 23292 ns 31096
|
||||
BM_Summary_Collect_Common/32768 49831 ns 49292 ns 13492
|
||||
BM_Summary_Collect_Common/262144 128723 ns 126987 ns 5579
|
||||
```
|
||||
|
||||
## Project Status
|
||||
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.
|
||||
|
||||
## FAQ
|
||||
|
||||
### What scrape formats do you support
|
||||
|
||||
Only the [Prometheus Text Exposition
|
||||
Format](https://github.com/prometheus/docs/blob/master/content/docs/instrumenting/exposition_formats.md#text-format-details).
|
||||
Support for the protobuf format was removed because it's been removed
|
||||
from Prometheus 2.0.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
@@ -0,0 +1,5 @@
|
||||
workspace(name = "com_github_jupp0r_prometheus_cpp")
|
||||
|
||||
load("//bazel:repositories.bzl", "prometheus_cpp_repositories")
|
||||
|
||||
prometheus_cpp_repositories()
|
||||
@@ -0,0 +1,7 @@
|
||||
exports_files(
|
||||
glob([
|
||||
"*.BUILD",
|
||||
"*.tpl",
|
||||
]),
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
@@ -0,0 +1,103 @@
|
||||
licenses(["notice"]) # MIT license
|
||||
|
||||
config_setting(
|
||||
name = "osx",
|
||||
constraint_values = [
|
||||
"@bazel_tools//platforms:osx",
|
||||
],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "windows",
|
||||
constraint_values = [
|
||||
"@bazel_tools//platforms:windows",
|
||||
],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "with_ssl",
|
||||
define_values = {
|
||||
"with_civetweb_ssl": "true",
|
||||
},
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
COPTS = [
|
||||
"-DUSE_IPV6",
|
||||
"-DNDEBUG",
|
||||
"-DNO_CGI",
|
||||
"-DNO_CACHING",
|
||||
"-DNO_FILES",
|
||||
"-UDEBUG",
|
||||
] + select({
|
||||
":with_ssl": [
|
||||
"-DOPENSSL_API_1_1",
|
||||
"-DNO_SSL_DL",
|
||||
],
|
||||
"@//conditions:default": [
|
||||
"-DNO_SSL",
|
||||
],
|
||||
})
|
||||
|
||||
DEPS = select({
|
||||
":with_ssl": [
|
||||
"@boringssl//:crypto",
|
||||
"@boringssl//:ssl",
|
||||
],
|
||||
"@//conditions:default": [],
|
||||
})
|
||||
|
||||
cc_library(
|
||||
name = "libcivetweb",
|
||||
srcs = [
|
||||
"src/civetweb.c",
|
||||
"src/response.inl",
|
||||
],
|
||||
hdrs = [
|
||||
"include/civetweb.h",
|
||||
],
|
||||
copts = COPTS,
|
||||
includes = [
|
||||
"include",
|
||||
],
|
||||
linkopts = select({
|
||||
":windows": [],
|
||||
"//conditions:default": ["-lpthread"],
|
||||
}) + select({
|
||||
":osx": [],
|
||||
":windows": [],
|
||||
"//conditions:default": ["-lrt"],
|
||||
}),
|
||||
textual_hdrs = [
|
||||
"src/md5.inl",
|
||||
"src/handle_form.inl",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = DEPS,
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "civetweb",
|
||||
srcs = [
|
||||
"src/CivetServer.cpp",
|
||||
],
|
||||
hdrs = [
|
||||
"include/CivetServer.h",
|
||||
],
|
||||
copts = COPTS,
|
||||
includes = [
|
||||
"include",
|
||||
],
|
||||
linkopts = select({
|
||||
":windows": [],
|
||||
"//conditions:default": ["-lpthread"],
|
||||
}) + select({
|
||||
":osx": [],
|
||||
":windows": [],
|
||||
"//conditions:default": ["-lrt"],
|
||||
}),
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":libcivetweb",
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,72 @@
|
||||
# Copyright 2017, OpenCensus Authors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# copied from: https://github.com/census-instrumentation/opencensus-cpp/blob/master/WORKSPACE
|
||||
|
||||
licenses(["notice"]) # MIT/X derivative license
|
||||
|
||||
load("@com_github_jupp0r_prometheus_cpp//bazel:curl.bzl", "CURL_COPTS")
|
||||
|
||||
package(features = ["no_copts_tokenization"])
|
||||
|
||||
config_setting(
|
||||
name = "windows",
|
||||
constraint_values = [
|
||||
"@bazel_tools//platforms:windows",
|
||||
],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "osx",
|
||||
constraint_values = [
|
||||
"@bazel_tools//platforms:osx",
|
||||
],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "curl",
|
||||
srcs = glob([
|
||||
"lib/**/*.c",
|
||||
]),
|
||||
hdrs = glob([
|
||||
"include/curl/*.h",
|
||||
"lib/**/*.h",
|
||||
]),
|
||||
copts = CURL_COPTS + [
|
||||
'-DOS="os"',
|
||||
],
|
||||
defines = ["CURL_STATICLIB"],
|
||||
includes = [
|
||||
"include/",
|
||||
"lib/",
|
||||
],
|
||||
linkopts = select({
|
||||
"//:windows": [
|
||||
"-DEFAULTLIB:ws2_32.lib",
|
||||
"-DEFAULTLIB:advapi32.lib",
|
||||
"-DEFAULTLIB:crypt32.lib",
|
||||
"-DEFAULTLIB:Normaliz.lib",
|
||||
],
|
||||
"//:osx": [
|
||||
"-framework SystemConfiguration",
|
||||
"-lpthread",
|
||||
],
|
||||
"//conditions:default": [
|
||||
"-lpthread",
|
||||
],
|
||||
}),
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
@@ -0,0 +1,201 @@
|
||||
# Copyright 2018, OpenCensus Authors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Compiler options for building libcurl.
|
||||
# copied from: https://github.com/census-instrumentation/opencensus-cpp/blob/master/opencensus/curl.bzl
|
||||
|
||||
BASE_CURL_COPTS = [
|
||||
# Disable everything else except HTTP protocol.
|
||||
"-DHTTP_ONLY=1",
|
||||
"-DENABLE_IPV6=1",
|
||||
"-DGETHOSTNAME_TYPE_ARG2=size_t",
|
||||
"-DGETSERVBYPORT_R_ARGS=6",
|
||||
"-DGETSERVBYPORT_R_BUFSIZE=4096",
|
||||
"-DHAVE_ALARM=1",
|
||||
"-DHAVE_ALLOCA_H=1",
|
||||
"-DHAVE_ARPA_INET_H=1",
|
||||
"-DHAVE_ARPA_TFTP_H=1",
|
||||
"-DHAVE_ASSERT_H=1",
|
||||
"-DHAVE_BASENAME=1",
|
||||
"-DHAVE_BOOL_T=1",
|
||||
"-DHAVE_CLOCK_GETTIME_MONOTONIC=1",
|
||||
"-DHAVE_CONNECT=1",
|
||||
"-DHAVE_DLFCN_H=1",
|
||||
"-DHAVE_ENGINE_LOAD_BUILTIN_ENGINES=1",
|
||||
"-DHAVE_ERRNO_H=1",
|
||||
"-DHAVE_FCNTL=1",
|
||||
"-DHAVE_FCNTL_H=1",
|
||||
"-DHAVE_FCNTL_O_NONBLOCK=1",
|
||||
"-DHAVE_FDOPEN=1",
|
||||
"-DHAVE_FREEADDRINFO=1",
|
||||
"-DHAVE_FREEIFADDRS=1",
|
||||
"-DHAVE_FSETXATTR=1",
|
||||
"-DHAVE_FSETXATTR_5=1",
|
||||
"-DHAVE_FTRUNCATE=1",
|
||||
"-DHAVE_GAI_STRERROR=1",
|
||||
"-DHAVE_GETADDRINFO=1",
|
||||
"-DHAVE_GETADDRINFO_THREADSAFE=1",
|
||||
"-DHAVE_GETEUID=1",
|
||||
"-DHAVE_GETHOSTBYADDR=1",
|
||||
"-DHAVE_GETHOSTBYADDR_R=1",
|
||||
"-DHAVE_GETHOSTBYADDR_R_8=1",
|
||||
"-DHAVE_GETHOSTBYNAME=1",
|
||||
"-DHAVE_GETHOSTBYNAME_R=1",
|
||||
"-DHAVE_GETHOSTBYNAME_R_6=1",
|
||||
"-DHAVE_GETHOSTNAME=1",
|
||||
"-DHAVE_GETIFADDRS=1",
|
||||
"-DHAVE_GETPPID=1",
|
||||
"-DHAVE_GETPWUID=1",
|
||||
"-DHAVE_GETPWUID_R=1",
|
||||
"-DHAVE_GETRLIMIT=1",
|
||||
"-DHAVE_GETSERVBYPORT_R=1",
|
||||
"-DHAVE_GETTIMEOFDAY=1",
|
||||
"-DHAVE_GMTIME_R=1",
|
||||
"-DHAVE_IFADDRS_H=1",
|
||||
"-DHAVE_IF_NAMETOINDEX=1",
|
||||
"-DHAVE_INET_NTOP=1",
|
||||
"-DHAVE_INET_PTON=1",
|
||||
"-DHAVE_INTTYPES_H=1",
|
||||
"-DHAVE_IOCTL=1",
|
||||
"-DHAVE_IOCTL_FIONBIO=1",
|
||||
"-DHAVE_IOCTL_SIOCGIFADDR=1",
|
||||
"-DHAVE_LIBGEN_H=1",
|
||||
"-DHAVE_LL=1",
|
||||
"-DHAVE_LOCALE_H=1",
|
||||
"-DHAVE_LOCALTIME_R=1",
|
||||
"-DHAVE_LONGLONG=1",
|
||||
"-DHAVE_MALLOC_H=1",
|
||||
"-DHAVE_MEMORY_H=1",
|
||||
"-DHAVE_NETDB_H=1",
|
||||
"-DHAVE_NETINET_IN_H=1",
|
||||
"-DHAVE_NETINET_TCP_H=1",
|
||||
"-DHAVE_NET_IF_H=1",
|
||||
"-DHAVE_PIPE=1",
|
||||
"-DHAVE_POLL=1",
|
||||
"-DHAVE_POLL_FINE=1",
|
||||
"-DHAVE_POLL_H=1",
|
||||
"-DHAVE_POSIX_STRERROR_R=1",
|
||||
"-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",
|
||||
"-DHAVE_SETLOCALE=1",
|
||||
"-DHAVE_SETRLIMIT=1",
|
||||
"-DHAVE_SETSOCKOPT=1",
|
||||
"-DHAVE_SGTTY_H=1",
|
||||
"-DHAVE_SIGACTION=1",
|
||||
"-DHAVE_SIGINTERRUPT=1",
|
||||
"-DHAVE_SIGNAL=1",
|
||||
"-DHAVE_SIGNAL_H=1",
|
||||
"-DHAVE_SIGSETJMP=1",
|
||||
"-DHAVE_SIG_ATOMIC_T=1",
|
||||
"-DHAVE_SOCKADDR_IN6_SIN6_SCOPE_ID=1",
|
||||
"-DHAVE_SOCKET=1",
|
||||
"-DHAVE_SOCKETPAIR=1",
|
||||
"-DHAVE_STDBOOL_H=1",
|
||||
"-DHAVE_STDINT_H=1",
|
||||
"-DHAVE_STDIO_H=1",
|
||||
"-DHAVE_STDLIB_H=1",
|
||||
"-DHAVE_STRCASECMP=1",
|
||||
"-DHAVE_STRDUP=1",
|
||||
"-DHAVE_STRERROR_R=1",
|
||||
"-DHAVE_STRINGS_H=1",
|
||||
"-DHAVE_STRING_H=1",
|
||||
"-DHAVE_STRNCASECMP=1",
|
||||
"-DHAVE_STRSTR=1",
|
||||
"-DHAVE_STRTOK_R=1",
|
||||
"-DHAVE_STRTOLL=1",
|
||||
"-DHAVE_STRUCT_SOCKADDR_STORAGE=1",
|
||||
"-DHAVE_STRUCT_TIMEVAL=1",
|
||||
"-DHAVE_SYS_IOCTL_H=1",
|
||||
"-DHAVE_SYS_PARAM_H=1",
|
||||
"-DHAVE_SYS_POLL_H=1",
|
||||
"-DHAVE_SYS_RESOURCE_H=1",
|
||||
"-DHAVE_SYS_SELECT_H=1",
|
||||
"-DHAVE_SYS_SOCKET_H=1",
|
||||
"-DHAVE_SYS_STAT_H=1",
|
||||
"-DHAVE_SYS_TIME_H=1",
|
||||
"-DHAVE_SYS_TYPES_H=1",
|
||||
"-DHAVE_SYS_UIO_H=1",
|
||||
"-DHAVE_SYS_UN_H=1",
|
||||
"-DHAVE_SYS_WAIT_H=1",
|
||||
"-DHAVE_SYS_XATTR_H=1",
|
||||
"-DHAVE_TERMIOS_H=1",
|
||||
"-DHAVE_TERMIO_H=1",
|
||||
"-DHAVE_TIME_H=1",
|
||||
"-DHAVE_UNISTD_H=1",
|
||||
"-DHAVE_UTIME=1",
|
||||
"-DHAVE_UTIMES=1",
|
||||
"-DHAVE_UTIME_H=1",
|
||||
"-DHAVE_VARIADIC_MACROS_C99=1",
|
||||
"-DHAVE_VARIADIC_MACROS_GCC=1",
|
||||
"-DHAVE_WRITABLE_ARGV=1",
|
||||
"-DHAVE_WRITEV=1",
|
||||
"-DRECV_TYPE_ARG1=int",
|
||||
"-DRECV_TYPE_ARG2=void*",
|
||||
"-DRECV_TYPE_ARG3=size_t",
|
||||
"-DRECV_TYPE_ARG4=int",
|
||||
"-DRECV_TYPE_RETV=ssize_t",
|
||||
"-DSELECT_QUAL_ARG5=",
|
||||
"-DSELECT_TYPE_ARG1=int",
|
||||
"-DSELECT_TYPE_ARG234=fd_set*",
|
||||
"-DSELECT_TYPE_RETV=int",
|
||||
"-DSEND_QUAL_ARG2=const",
|
||||
"-DSEND_TYPE_ARG1=int",
|
||||
"-DSEND_TYPE_ARG2=void*",
|
||||
"-DSEND_TYPE_ARG3=size_t",
|
||||
"-DSEND_TYPE_ARG4=int",
|
||||
"-DSEND_TYPE_RETV=ssize_t",
|
||||
"-DSIZEOF_CURL_OFF_T=8",
|
||||
"-DSIZEOF_INT=4",
|
||||
"-DSIZEOF_LONG=8",
|
||||
"-DSIZEOF_OFF_T=8",
|
||||
"-DSIZEOF_SHORT=2",
|
||||
"-DSIZEOF_SIZE_T=8",
|
||||
"-DSIZEOF_TIME_T=8",
|
||||
"-DSTDC_HEADERS=1",
|
||||
"-DSTRERROR_R_TYPE_ARG3=size_t",
|
||||
"-DTIME_WITH_SYS_TIME=1",
|
||||
"-DUSE_THREADS_POSIX=1",
|
||||
"-DUSE_UNIX_SOCKETS=1",
|
||||
|
||||
# Extra defines needed by curl
|
||||
"-DBUILDING_LIBCURL",
|
||||
"-DCURL_HIDDEN_SYMBOLS",
|
||||
]
|
||||
|
||||
LINUX_CURL_COPTS = [
|
||||
"-DHAVE_LINUX_TCP_H=1",
|
||||
"-DHAVE_MSG_NOSIGNAL=1",
|
||||
]
|
||||
|
||||
CURL_COPTS = select({
|
||||
"//:windows": [
|
||||
# Disable everything else except HTTP protocol.
|
||||
"/DHTTP_ONLY=1",
|
||||
"/DCURL_STATICLIB",
|
||||
"/DWIN32",
|
||||
"/DBUILDING_LIBCURL",
|
||||
"/DUSE_WIN32_IDN",
|
||||
"/DWANT_IDN_PROTOTYPES",
|
||||
"/DUSE_IPV6",
|
||||
"/DUSE_WINDOWS_SSPI",
|
||||
"/DUSE_SCHANNEL",
|
||||
],
|
||||
"//:osx": BASE_CURL_COPTS,
|
||||
"//conditions:default": BASE_CURL_COPTS + LINUX_CURL_COPTS,
|
||||
})
|
||||
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#define {BASE_NAME}_EXPORT
|
||||
#define {BASE_NAME}_NO_EXPORT
|
||||
@@ -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}"},
|
||||
)
|
||||
@@ -0,0 +1,72 @@
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
|
||||
|
||||
def prometheus_cpp_repositories():
|
||||
maybe(
|
||||
http_archive,
|
||||
name = "civetweb",
|
||||
strip_prefix = "civetweb-1.15",
|
||||
sha256 = "90a533422944ab327a4fbb9969f0845d0dba05354f9cacce3a5005fa59f593b9",
|
||||
urls = [
|
||||
"https://github.com/civetweb/civetweb/archive/v1.15.tar.gz",
|
||||
],
|
||||
build_file = "@com_github_jupp0r_prometheus_cpp//bazel:civetweb.BUILD",
|
||||
)
|
||||
|
||||
maybe(
|
||||
http_archive,
|
||||
name = "com_google_googletest",
|
||||
sha256 = "b4870bf121ff7795ba20d20bcdd8627b8e088f2d1dab299a031c1034eddc93d5",
|
||||
strip_prefix = "googletest-release-1.11.0",
|
||||
urls = [
|
||||
"https://github.com/google/googletest/archive/release-1.11.0.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
maybe(
|
||||
http_archive,
|
||||
name = "com_github_curl",
|
||||
sha256 = "3c6893d38d054d4e378267166858698899e9d87258e8ff1419d020c395384535",
|
||||
strip_prefix = "curl-7.84.0",
|
||||
urls = [
|
||||
"https://github.com/curl/curl/releases/download/curl-7_84_0/curl-7.84.0.tar.gz",
|
||||
"https://curl.haxx.se/download/curl-7.84.0.tar.gz",
|
||||
],
|
||||
build_file = "@com_github_jupp0r_prometheus_cpp//bazel:curl.BUILD",
|
||||
)
|
||||
|
||||
maybe(
|
||||
http_archive,
|
||||
name = "com_github_google_benchmark",
|
||||
sha256 = "6132883bc8c9b0df5375b16ab520fac1a85dc9e4cf5be59480448ece74b278d4",
|
||||
strip_prefix = "benchmark-1.6.1",
|
||||
urls = [
|
||||
"https://github.com/google/benchmark/archive/v1.6.1.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
maybe(
|
||||
http_archive,
|
||||
name = "net_zlib_zlib",
|
||||
sha256 = "91844808532e5ce316b3c010929493c0244f3d37593afd6de04f71821d5136d9",
|
||||
strip_prefix = "zlib-1.2.12",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/zlib.net/zlib-1.2.12.tar.gz",
|
||||
"https://zlib.net/zlib-1.2.12.tar.gz",
|
||||
"https://storage.googleapis.com/bazel-mirror/zlib.net/zlib-1.2.12.tar.gz",
|
||||
],
|
||||
build_file = "@com_github_jupp0r_prometheus_cpp//bazel:zlib.BUILD",
|
||||
)
|
||||
|
||||
maybe(
|
||||
http_archive,
|
||||
name = "boringssl",
|
||||
# Use github mirror instead of https://boringssl.googlesource.com/boringssl
|
||||
# to obtain a boringssl archive with consistent sha256
|
||||
sha256 = "534fa658bd845fd974b50b10f444d392dfd0d93768c4a51b61263fd37d851c40",
|
||||
strip_prefix = "boringssl-b9232f9e27e5668bc0414879dcdedb2a59ea75f2",
|
||||
urls = [
|
||||
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/boringssl/archive/b9232f9e27e5668bc0414879dcdedb2a59ea75f2.tar.gz",
|
||||
"https://github.com/google/boringssl/archive/b9232f9e27e5668bc0414879dcdedb2a59ea75f2.tar.gz",
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,16 @@
|
||||
# copied from: https://github.com/bazelbuild/bazel/blob/master/third_party/zlib/BUILD
|
||||
|
||||
licenses(["notice"]) # BSD/MIT-like license (for zlib)
|
||||
|
||||
cc_library(
|
||||
name = "z",
|
||||
srcs = glob(["*.c"]),
|
||||
hdrs = glob(["*.h"]),
|
||||
# Use -Dverbose=-1 to turn off zlib's trace logging. (bazelbuild/bazel#3280)
|
||||
copts = [
|
||||
"-w",
|
||||
"-Dverbose=-1",
|
||||
],
|
||||
includes = ["."],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
@@ -0,0 +1,5 @@
|
||||
[
|
||||
{ include: [ "@<gmock/.*>", private, "<gmock/gmock.h>", public ] },
|
||||
{ include: [ "@<gtest/.*>", private, "<gtest/gtest.h>", public ] },
|
||||
{ include: [ "@<bits/this_thread_sleep.h>", private, "<thread>", public ]}
|
||||
]
|
||||
@@ -0,0 +1,15 @@
|
||||
cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
|
||||
|
||||
project(prometheus-cpp-import)
|
||||
|
||||
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()
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../push/tests/integration/sample_client.cc
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../pull/tests/integration/sample_server.cc
|
||||
@@ -0,0 +1,21 @@
|
||||
cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
|
||||
|
||||
project(prometheus-cpp-import)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
|
||||
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()
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../push/tests/integration/sample_client.cc
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../pull/tests/integration/sample_server.cc
|
||||
@@ -0,0 +1,34 @@
|
||||
@PACKAGE_INIT@
|
||||
include(CMakeFindDependencyMacro)
|
||||
|
||||
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()
|
||||
|
||||
if(PROMETHEUS_CPP_ENABLE_PUSH)
|
||||
find_dependency(CURL)
|
||||
endif()
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/prometheus-cpp-targets.cmake")
|
||||
@@ -0,0 +1,14 @@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=${prefix}
|
||||
includedir=@PROMETHEUS_CPP_PKGCONFIG_INCLUDEDIR@
|
||||
libdir=@PROMETHEUS_CPP_PKGCONFIG_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@
|
||||
@@ -0,0 +1,14 @@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=${prefix}
|
||||
includedir=@PROMETHEUS_CPP_PKGCONFIG_INCLUDEDIR@
|
||||
libdir=@PROMETHEUS_CPP_PKGCONFIG_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@
|
||||
@@ -0,0 +1,14 @@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=${prefix}
|
||||
includedir=@PROMETHEUS_CPP_PKGCONFIG_INCLUDEDIR@
|
||||
libdir=@PROMETHEUS_CPP_PKGCONFIG_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@
|
||||
@@ -0,0 +1,20 @@
|
||||
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([
|
||||
"src/**/*.cc",
|
||||
"src/**/*.h",
|
||||
]),
|
||||
hdrs = glob(
|
||||
["include/**/*.h"],
|
||||
) + [":export_header"],
|
||||
strip_include_prefix = "include",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
@@ -0,0 +1,100 @@
|
||||
|
||||
add_library(core
|
||||
src/check_names.cc
|
||||
src/counter.cc
|
||||
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/histogram.cc
|
||||
src/info.cc
|
||||
src/registry.cc
|
||||
src/serializer.cc
|
||||
src/summary.cc
|
||||
src/text_serializer.cc
|
||||
)
|
||||
|
||||
add_library(${PROJECT_NAME}::core ALIAS core)
|
||||
|
||||
target_compile_features(core
|
||||
PUBLIC
|
||||
cxx_std_14
|
||||
)
|
||||
|
||||
target_link_libraries(core
|
||||
PRIVATE
|
||||
Threads::Threads
|
||||
$<$<AND:$<BOOL:UNIX>,$<NOT:$<BOOL:APPLE>>>: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
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
|
||||
)
|
||||
|
||||
set_target_properties(core
|
||||
PROPERTIES
|
||||
OUTPUT_NAME ${PROJECT_NAME}-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
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
)
|
||||
|
||||
install(
|
||||
DIRECTORY include/ ${CMAKE_CURRENT_BINARY_DIR}/include/
|
||||
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
|
||||
)
|
||||
|
||||
unset(PKGCONFIG_LIBS)
|
||||
unset(PKGCONFIG_REQUIRES)
|
||||
endif()
|
||||
|
||||
if(ENABLE_TESTING)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
if(benchmark_FOUND)
|
||||
add_subdirectory(benchmarks)
|
||||
endif()
|
||||
@@ -0,0 +1,12 @@
|
||||
cc_binary(
|
||||
name = "benchmarks",
|
||||
srcs = glob([
|
||||
"*.cc",
|
||||
"*.h",
|
||||
]),
|
||||
linkstatic = True,
|
||||
deps = [
|
||||
"//core",
|
||||
"@com_github_google_benchmark//:benchmark",
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
add_executable(benchmarks
|
||||
main.cc
|
||||
benchmark_helpers.cc
|
||||
benchmark_helpers.h
|
||||
counter_bench.cc
|
||||
gauge_bench.cc
|
||||
histogram_bench.cc
|
||||
info_bench.cc
|
||||
registry_bench.cc
|
||||
summary_bench.cc
|
||||
)
|
||||
|
||||
target_link_libraries(benchmarks
|
||||
PRIVATE
|
||||
${PROJECT_NAME}::core
|
||||
benchmark::benchmark
|
||||
)
|
||||
|
||||
add_test(
|
||||
NAME benchmarks
|
||||
COMMAND benchmarks
|
||||
)
|
||||
|
||||
set_property(
|
||||
TEST benchmarks
|
||||
APPEND PROPERTY LABELS Benchmark
|
||||
)
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "benchmark_helpers.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <map>
|
||||
|
||||
std::string GenerateRandomString(std::size_t length) {
|
||||
auto randchar = []() -> char {
|
||||
const char charset[] = "abcdefghijklmnopqrstuvwxyz";
|
||||
const std::size_t max_index = (sizeof(charset) - 1);
|
||||
return charset[rand() % max_index];
|
||||
};
|
||||
std::string str(length, 0);
|
||||
std::generate_n(str.begin(), length, randchar);
|
||||
return str;
|
||||
}
|
||||
|
||||
prometheus::Labels GenerateRandomLabels(std::size_t number_of_pairs) {
|
||||
const auto label_character_count = 10;
|
||||
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)});
|
||||
}
|
||||
return label_pairs;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
|
||||
#include "prometheus/labels.h"
|
||||
|
||||
std::string GenerateRandomString(std::size_t length);
|
||||
prometheus::Labels GenerateRandomLabels(std::size_t number_of_labels);
|
||||
@@ -0,0 +1,33 @@
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
#include "prometheus/counter.h"
|
||||
#include "prometheus/family.h"
|
||||
#include "prometheus/registry.h"
|
||||
|
||||
static void BM_Counter_Increment(benchmark::State& state) {
|
||||
using prometheus::BuildCounter;
|
||||
using prometheus::Counter;
|
||||
using prometheus::Registry;
|
||||
Registry registry;
|
||||
auto& counter_family =
|
||||
BuildCounter().Name("benchmark_counter").Help("").Register(registry);
|
||||
auto& counter = counter_family.Add({});
|
||||
|
||||
while (state.KeepRunning()) counter.Increment();
|
||||
}
|
||||
BENCHMARK(BM_Counter_Increment);
|
||||
|
||||
static void BM_Counter_Collect(benchmark::State& state) {
|
||||
using prometheus::BuildCounter;
|
||||
using prometheus::Counter;
|
||||
using prometheus::Registry;
|
||||
Registry registry;
|
||||
auto& counter_family =
|
||||
BuildCounter().Name("benchmark_counter").Help("").Register(registry);
|
||||
auto& counter = counter_family.Add({});
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
benchmark::DoNotOptimize(counter.Collect());
|
||||
};
|
||||
}
|
||||
BENCHMARK(BM_Counter_Collect);
|
||||
@@ -0,0 +1,59 @@
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
#include "prometheus/family.h"
|
||||
#include "prometheus/gauge.h"
|
||||
#include "prometheus/registry.h"
|
||||
|
||||
static void BM_Gauge_Increment(benchmark::State& state) {
|
||||
using prometheus::BuildGauge;
|
||||
using prometheus::Gauge;
|
||||
using prometheus::Registry;
|
||||
Registry registry;
|
||||
auto& gauge_family =
|
||||
BuildGauge().Name("benchmark_gauge").Help("").Register(registry);
|
||||
auto& gauge = gauge_family.Add({});
|
||||
|
||||
while (state.KeepRunning()) gauge.Increment(2);
|
||||
}
|
||||
BENCHMARK(BM_Gauge_Increment);
|
||||
|
||||
static void BM_Gauge_Decrement(benchmark::State& state) {
|
||||
using prometheus::BuildGauge;
|
||||
using prometheus::Gauge;
|
||||
using prometheus::Registry;
|
||||
Registry registry;
|
||||
auto& gauge_family =
|
||||
BuildGauge().Name("benchmark_gauge").Help("").Register(registry);
|
||||
auto& gauge = gauge_family.Add({});
|
||||
|
||||
while (state.KeepRunning()) gauge.Decrement(2);
|
||||
}
|
||||
BENCHMARK(BM_Gauge_Decrement);
|
||||
|
||||
static void BM_Gauge_SetToCurrentTime(benchmark::State& state) {
|
||||
using prometheus::BuildGauge;
|
||||
using prometheus::Gauge;
|
||||
using prometheus::Registry;
|
||||
Registry registry;
|
||||
auto& gauge_family =
|
||||
BuildGauge().Name("benchmark_gauge").Help("").Register(registry);
|
||||
auto& gauge = gauge_family.Add({});
|
||||
|
||||
while (state.KeepRunning()) gauge.SetToCurrentTime();
|
||||
}
|
||||
BENCHMARK(BM_Gauge_SetToCurrentTime);
|
||||
|
||||
static void BM_Gauge_Collect(benchmark::State& state) {
|
||||
using prometheus::BuildGauge;
|
||||
using prometheus::Gauge;
|
||||
using prometheus::Registry;
|
||||
Registry registry;
|
||||
auto& gauge_family =
|
||||
BuildGauge().Name("benchmark_gauge").Help("").Register(registry);
|
||||
auto& gauge = gauge_family.Add({});
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
benchmark::DoNotOptimize(gauge.Collect());
|
||||
};
|
||||
}
|
||||
BENCHMARK(BM_Gauge_Collect);
|
||||
@@ -0,0 +1,70 @@
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
|
||||
#include "prometheus/family.h"
|
||||
#include "prometheus/histogram.h"
|
||||
#include "prometheus/registry.h"
|
||||
|
||||
using prometheus::Histogram;
|
||||
|
||||
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);
|
||||
}
|
||||
return bucket_boundaries;
|
||||
}
|
||||
|
||||
static void BM_Histogram_Observe(benchmark::State& state) {
|
||||
using prometheus::BuildHistogram;
|
||||
using prometheus::Histogram;
|
||||
using prometheus::Registry;
|
||||
|
||||
const auto number_of_buckets = state.range(0);
|
||||
|
||||
Registry registry;
|
||||
auto& histogram_family =
|
||||
BuildHistogram().Name("benchmark_histogram").Help("").Register(registry);
|
||||
auto bucket_boundaries = CreateLinearBuckets(0, number_of_buckets - 1, 1);
|
||||
auto& histogram = histogram_family.Add({}, bucket_boundaries);
|
||||
std::random_device rd;
|
||||
std::mt19937 gen(rd());
|
||||
std::uniform_real_distribution<> d(0, number_of_buckets);
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
auto observation = d(gen);
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
histogram.Observe(observation);
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
|
||||
auto elapsed_seconds =
|
||||
std::chrono::duration_cast<std::chrono::duration<double>>(end - start);
|
||||
state.SetIterationTime(elapsed_seconds.count());
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_Histogram_Observe)->Range(0, 4096);
|
||||
|
||||
static void BM_Histogram_Collect(benchmark::State& state) {
|
||||
using prometheus::BuildHistogram;
|
||||
using prometheus::Histogram;
|
||||
using prometheus::Registry;
|
||||
|
||||
const auto number_of_buckets = state.range(0);
|
||||
|
||||
Registry registry;
|
||||
auto& histogram_family =
|
||||
BuildHistogram().Name("benchmark_histogram").Help("").Register(registry);
|
||||
auto bucket_boundaries = CreateLinearBuckets(0, number_of_buckets - 1, 1);
|
||||
auto& histogram = histogram_family.Add({}, bucket_boundaries);
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
benchmark::DoNotOptimize(histogram.Collect());
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_Histogram_Collect)->Range(0, 4096);
|
||||
@@ -0,0 +1,20 @@
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
#include "prometheus/family.h"
|
||||
#include "prometheus/info.h"
|
||||
#include "prometheus/registry.h"
|
||||
|
||||
static void BM_Info_Collect(benchmark::State& state) {
|
||||
using prometheus::BuildInfo;
|
||||
using prometheus::Info;
|
||||
using prometheus::Registry;
|
||||
Registry registry;
|
||||
auto& info_family =
|
||||
BuildInfo().Name("benchmark_info").Help("").Register(registry);
|
||||
auto& info = info_family.Add({});
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
benchmark::DoNotOptimize(info.Collect());
|
||||
};
|
||||
}
|
||||
BENCHMARK(BM_Info_Collect);
|
||||
@@ -0,0 +1,3 @@
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
BENCHMARK_MAIN();
|
||||
@@ -0,0 +1,44 @@
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#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;
|
||||
using prometheus::Counter;
|
||||
using prometheus::Registry;
|
||||
Registry registry;
|
||||
|
||||
while (state.KeepRunning())
|
||||
BuildCounter().Name("benchmark_counter").Help("").Register(registry);
|
||||
}
|
||||
BENCHMARK(BM_Registry_CreateFamily);
|
||||
|
||||
static void BM_Registry_CreateCounter(benchmark::State& state) {
|
||||
using prometheus::BuildCounter;
|
||||
using prometheus::Counter;
|
||||
using prometheus::Registry;
|
||||
Registry registry;
|
||||
auto& counter_family = BuildCounter()
|
||||
.Labels(GenerateRandomLabels(10))
|
||||
.Name("benchmark_counter")
|
||||
.Help("")
|
||||
.Register(registry);
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
auto labels = GenerateRandomLabels(state.range(0));
|
||||
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
counter_family.Add(labels);
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
|
||||
auto elapsed_seconds =
|
||||
std::chrono::duration_cast<std::chrono::duration<double>>(end - start);
|
||||
state.SetIterationTime(elapsed_seconds.count());
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_Registry_CreateCounter)->Range(0, 4096);
|
||||
@@ -0,0 +1,139 @@
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
|
||||
#include "prometheus/family.h"
|
||||
#include "prometheus/registry.h"
|
||||
#include "prometheus/summary.h"
|
||||
|
||||
using prometheus::Summary;
|
||||
|
||||
static const auto ITERATIONS = 262144;
|
||||
|
||||
static Summary::Quantiles CreateLinearQuantiles(int count) {
|
||||
static auto generator = [](double x) {
|
||||
static auto exp = [](double x) {
|
||||
static const double A = 2;
|
||||
return 1 - std::exp(-A * x);
|
||||
};
|
||||
|
||||
return exp(x) / exp(1);
|
||||
};
|
||||
|
||||
auto quantiles = Summary::Quantiles{};
|
||||
for (auto i = 0; i < count; ++i) {
|
||||
quantiles.emplace_back(generator(double(i) / count), 0.01);
|
||||
}
|
||||
return quantiles;
|
||||
}
|
||||
|
||||
static void BM_Summary_Observe(benchmark::State& state) {
|
||||
using prometheus::BuildSummary;
|
||||
using prometheus::Registry;
|
||||
using prometheus::Summary;
|
||||
|
||||
const auto number_of_quantiles = state.range(0);
|
||||
|
||||
Registry registry;
|
||||
auto& summary_family =
|
||||
BuildSummary().Name("benchmark_summary").Help("").Register(registry);
|
||||
auto quantiles = CreateLinearQuantiles(number_of_quantiles);
|
||||
auto& summary = summary_family.Add({}, quantiles);
|
||||
std::random_device rd;
|
||||
std::mt19937 gen(rd());
|
||||
std::uniform_real_distribution<> d(0, 100);
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
auto observation = d(gen);
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
summary.Observe(observation);
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
|
||||
auto elapsed_seconds =
|
||||
std::chrono::duration_cast<std::chrono::duration<double>>(end - start);
|
||||
state.SetIterationTime(elapsed_seconds.count());
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_Summary_Observe)->Range(0, 64)->Iterations(ITERATIONS);
|
||||
|
||||
static void BM_Summary_Collect(benchmark::State& state) {
|
||||
using prometheus::BuildSummary;
|
||||
using prometheus::Registry;
|
||||
using prometheus::Summary;
|
||||
|
||||
const auto number_of_quantiles = state.range(0);
|
||||
const auto number_of_entries = state.range(1);
|
||||
|
||||
Registry registry;
|
||||
auto& summary_family =
|
||||
BuildSummary().Name("benchmark_summary").Help("").Register(registry);
|
||||
auto quantiles = CreateLinearQuantiles(number_of_quantiles);
|
||||
auto& summary = summary_family.Add({}, quantiles);
|
||||
|
||||
std::random_device rd;
|
||||
std::mt19937 gen(rd());
|
||||
std::uniform_real_distribution<> d(0, 100);
|
||||
for (auto i = 1; i <= number_of_entries; ++i) summary.Observe(d(gen));
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
benchmark::DoNotOptimize(summary.Collect());
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_Summary_Collect)->RangePair(0, 64, 0, ITERATIONS);
|
||||
|
||||
static void BM_Summary_Observe_Common(benchmark::State& state) {
|
||||
using prometheus::BuildSummary;
|
||||
using prometheus::Registry;
|
||||
using prometheus::Summary;
|
||||
|
||||
Registry registry;
|
||||
auto& summary_family =
|
||||
BuildSummary().Name("benchmark_summary").Help("").Register(registry);
|
||||
auto& summary = summary_family.Add(
|
||||
{}, Summary::Quantiles{
|
||||
{0.5, 0.05}, {0.9, 0.01}, {0.95, 0.005}, {0.99, 0.001}});
|
||||
std::random_device rd;
|
||||
std::mt19937 gen(rd());
|
||||
std::uniform_real_distribution<> d(0, 100);
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
auto observation = d(gen);
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
summary.Observe(observation);
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
|
||||
auto elapsed_seconds =
|
||||
std::chrono::duration_cast<std::chrono::duration<double>>(end - start);
|
||||
state.SetIterationTime(elapsed_seconds.count());
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_Summary_Observe_Common)->Iterations(ITERATIONS);
|
||||
|
||||
static void BM_Summary_Collect_Common(benchmark::State& state) {
|
||||
using prometheus::BuildSummary;
|
||||
using prometheus::Registry;
|
||||
using prometheus::Summary;
|
||||
|
||||
const auto number_of_entries = state.range(0);
|
||||
|
||||
Registry registry;
|
||||
auto& summary_family =
|
||||
BuildSummary().Name("benchmark_summary").Help("").Register(registry);
|
||||
auto& summary = summary_family.Add(
|
||||
{}, Summary::Quantiles{
|
||||
{0.5, 0.05}, {0.9, 0.01}, {0.95, 0.005}, {0.99, 0.001}});
|
||||
|
||||
std::random_device rd;
|
||||
std::mt19937 gen(rd());
|
||||
std::uniform_real_distribution<> d(0, 100);
|
||||
for (auto i = 1; i <= number_of_entries; ++i) summary.Observe(d(gen));
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
benchmark::DoNotOptimize(summary.Collect());
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_Summary_Collect_Common)->Range(0, ITERATIONS);
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "prometheus/detail/core_export.h"
|
||||
#include "prometheus/metric_type.h"
|
||||
|
||||
namespace prometheus {
|
||||
|
||||
PROMETHEUS_CPP_CORE_EXPORT bool CheckMetricName(const std::string& name);
|
||||
PROMETHEUS_CPP_CORE_EXPORT bool CheckLabelName(const std::string& name,
|
||||
MetricType type);
|
||||
} // namespace prometheus
|
||||
@@ -0,0 +1,90 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "prometheus/detail/core_export.h"
|
||||
|
||||
namespace prometheus {
|
||||
|
||||
struct PROMETHEUS_CPP_CORE_EXPORT ClientMetric {
|
||||
// Label
|
||||
|
||||
struct Label {
|
||||
std::string name;
|
||||
std::string value;
|
||||
|
||||
bool operator<(const Label& rhs) const {
|
||||
return std::tie(name, value) < std::tie(rhs.name, rhs.value);
|
||||
}
|
||||
|
||||
bool operator==(const Label& rhs) const {
|
||||
return std::tie(name, value) == std::tie(rhs.name, rhs.value);
|
||||
}
|
||||
};
|
||||
std::vector<Label> label;
|
||||
|
||||
// Counter
|
||||
|
||||
struct Counter {
|
||||
double value = 0.0;
|
||||
};
|
||||
Counter counter;
|
||||
|
||||
// Gauge
|
||||
|
||||
struct Gauge {
|
||||
double value = 0.0;
|
||||
};
|
||||
Gauge gauge;
|
||||
|
||||
// Info
|
||||
|
||||
struct Info {
|
||||
double value = 1.0;
|
||||
};
|
||||
Info info;
|
||||
|
||||
// Summary
|
||||
|
||||
struct Quantile {
|
||||
double quantile = 0.0;
|
||||
double value = 0.0;
|
||||
};
|
||||
|
||||
struct Summary {
|
||||
std::uint64_t sample_count = 0;
|
||||
double sample_sum = 0.0;
|
||||
std::vector<Quantile> quantile;
|
||||
};
|
||||
Summary summary;
|
||||
|
||||
// Histogram
|
||||
|
||||
struct Bucket {
|
||||
std::uint64_t cumulative_count = 0;
|
||||
double upper_bound = 0.0;
|
||||
};
|
||||
|
||||
struct Histogram {
|
||||
std::uint64_t sample_count = 0;
|
||||
double sample_sum = 0.0;
|
||||
std::vector<Bucket> bucket;
|
||||
};
|
||||
Histogram histogram;
|
||||
|
||||
// Untyped
|
||||
|
||||
struct Untyped {
|
||||
double value = 0;
|
||||
};
|
||||
Untyped untyped;
|
||||
|
||||
// Timestamp
|
||||
|
||||
std::int64_t timestamp_ms = 0;
|
||||
};
|
||||
|
||||
} // namespace prometheus
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "prometheus/detail/core_export.h"
|
||||
|
||||
namespace prometheus {
|
||||
struct MetricFamily;
|
||||
}
|
||||
|
||||
namespace prometheus {
|
||||
|
||||
/// @brief Interface implemented by anything that can be used by Prometheus to
|
||||
/// collect metrics.
|
||||
///
|
||||
/// A Collectable has to be registered for collection. See Registry.
|
||||
class PROMETHEUS_CPP_CORE_EXPORT Collectable {
|
||||
public:
|
||||
virtual ~Collectable() = default;
|
||||
|
||||
/// \brief Returns a list of metrics and their samples.
|
||||
virtual std::vector<MetricFamily> Collect() const = 0;
|
||||
};
|
||||
|
||||
} // namespace prometheus
|
||||
@@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
|
||||
#include "prometheus/client_metric.h"
|
||||
#include "prometheus/detail/builder.h" // IWYU pragma: export
|
||||
#include "prometheus/detail/core_export.h"
|
||||
#include "prometheus/gauge.h"
|
||||
#include "prometheus/metric_type.h"
|
||||
|
||||
namespace prometheus {
|
||||
|
||||
/// \brief A counter metric to represent a monotonically increasing value.
|
||||
///
|
||||
/// This class represents the metric type counter:
|
||||
/// https://prometheus.io/docs/concepts/metric_types/#counter
|
||||
///
|
||||
/// The value of the counter can only increase. Example of counters are:
|
||||
/// - the number of requests served
|
||||
/// - tasks completed
|
||||
/// - errors
|
||||
///
|
||||
/// Do not use a counter to expose a value that can decrease - instead use a
|
||||
/// Gauge.
|
||||
///
|
||||
/// The class is thread-safe. No concurrent call to any API of this type causes
|
||||
/// a data race.
|
||||
class PROMETHEUS_CPP_CORE_EXPORT Counter {
|
||||
public:
|
||||
static const MetricType metric_type{MetricType::Counter};
|
||||
|
||||
/// \brief Create a counter that starts at 0.
|
||||
Counter() = default;
|
||||
|
||||
/// \brief Increment the counter by 1.
|
||||
void Increment();
|
||||
|
||||
/// \brief Increment the counter by a given amount.
|
||||
///
|
||||
/// The counter will not change if the given amount is negative.
|
||||
void Increment(double);
|
||||
|
||||
/// \brief Get the current value of the counter.
|
||||
double Value() const;
|
||||
|
||||
/// \brief Get the current value of the counter.
|
||||
///
|
||||
/// Collect is called by the Registry when collecting metrics.
|
||||
ClientMetric Collect() const;
|
||||
|
||||
private:
|
||||
Gauge gauge_{0.0};
|
||||
};
|
||||
|
||||
/// \brief Return a builder to configure and register a Counter metric.
|
||||
///
|
||||
/// @copydetails Family<>::Family()
|
||||
///
|
||||
/// Example usage:
|
||||
///
|
||||
/// \code
|
||||
/// auto registry = std::make_shared<Registry>();
|
||||
/// auto& counter_family = prometheus::BuildCounter()
|
||||
/// .Name("some_name")
|
||||
/// .Help("Additional description.")
|
||||
/// .Labels({{"key", "value"}})
|
||||
/// .Register(*registry);
|
||||
///
|
||||
/// ...
|
||||
/// \endcode
|
||||
///
|
||||
/// \return An object of unspecified type T, i.e., an implementation detail
|
||||
/// except that it has the following members:
|
||||
///
|
||||
/// - Name(const std::string&) to set the metric name,
|
||||
/// - Help(const std::string&) to set an additional description.
|
||||
/// - 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
|
||||
/// Register(Registry&).
|
||||
PROMETHEUS_CPP_CORE_EXPORT detail::Builder<Counter> BuildCounter();
|
||||
|
||||
} // namespace prometheus
|
||||
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "prometheus/labels.h"
|
||||
|
||||
// IWYU pragma: private
|
||||
// IWYU pragma: no_include "prometheus/family.h"
|
||||
|
||||
namespace prometheus {
|
||||
|
||||
template <typename T>
|
||||
class Family; // IWYU pragma: keep
|
||||
class Registry; // IWYU pragma: keep
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename T>
|
||||
class Builder {
|
||||
public:
|
||||
Builder& Labels(const ::prometheus::Labels& labels);
|
||||
Builder& Name(const std::string&);
|
||||
Builder& Help(const std::string&);
|
||||
Family<T>& Register(Registry&);
|
||||
|
||||
private:
|
||||
::prometheus::Labels labels_;
|
||||
std::string name_;
|
||||
std::string help_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace prometheus
|
||||
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
#include "prometheus/detail/core_export.h"
|
||||
|
||||
// IWYU pragma: private, include "prometheus/summary.h"
|
||||
|
||||
namespace prometheus {
|
||||
namespace detail {
|
||||
|
||||
class PROMETHEUS_CPP_CORE_EXPORT CKMSQuantiles {
|
||||
public:
|
||||
struct PROMETHEUS_CPP_CORE_EXPORT Quantile {
|
||||
Quantile(double quantile, double error);
|
||||
|
||||
double quantile;
|
||||
double error;
|
||||
double u;
|
||||
double v;
|
||||
};
|
||||
|
||||
private:
|
||||
struct Item {
|
||||
double value;
|
||||
int g;
|
||||
int delta;
|
||||
|
||||
Item(double value, int lower_delta, int delta);
|
||||
};
|
||||
|
||||
public:
|
||||
explicit CKMSQuantiles(const std::vector<Quantile>& quantiles);
|
||||
|
||||
void insert(double value);
|
||||
double get(double q);
|
||||
void reset();
|
||||
|
||||
private:
|
||||
double allowableError(int rank);
|
||||
bool insertBatch();
|
||||
void compress();
|
||||
|
||||
private:
|
||||
const std::reference_wrapper<const std::vector<Quantile>> quantiles_;
|
||||
|
||||
std::size_t count_;
|
||||
std::vector<Item> sample_;
|
||||
std::array<double, 500> buffer_;
|
||||
std::size_t buffer_count_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace prometheus
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
#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 {
|
||||
|
||||
class PROMETHEUS_CPP_CORE_EXPORT TimeWindowQuantiles {
|
||||
using Clock = std::chrono::steady_clock;
|
||||
|
||||
public:
|
||||
TimeWindowQuantiles(const std::vector<CKMSQuantiles::Quantile>& quantiles,
|
||||
Clock::duration max_age_seconds, int age_buckets);
|
||||
|
||||
double get(double q) const;
|
||||
void insert(double value);
|
||||
|
||||
private:
|
||||
CKMSQuantiles& rotate() const;
|
||||
|
||||
const std::vector<CKMSQuantiles::Quantile>& quantiles_;
|
||||
mutable std::vector<CKMSQuantiles> ckms_quantiles_;
|
||||
mutable std::size_t current_bucket_;
|
||||
|
||||
mutable Clock::time_point last_rotation_;
|
||||
const Clock::duration rotation_interval_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace prometheus
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "prometheus/detail/core_export.h"
|
||||
#include "prometheus/labels.h"
|
||||
|
||||
namespace prometheus {
|
||||
namespace detail {
|
||||
|
||||
/// \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 Labels& labels) const;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace prometheus
|
||||
@@ -0,0 +1,156 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "prometheus/client_metric.h"
|
||||
#include "prometheus/collectable.h"
|
||||
#include "prometheus/detail/core_export.h"
|
||||
#include "prometheus/detail/utils.h"
|
||||
#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/info.h"
|
||||
// IWYU pragma: no_include "prometheus/summary.h"
|
||||
|
||||
namespace prometheus {
|
||||
|
||||
/// \brief A metric of type T with a set of labeled dimensions.
|
||||
///
|
||||
/// One of Prometheus main feature is a multi-dimensional data model with time
|
||||
/// series data identified by metric name and key/value pairs, also known as
|
||||
/// labels. A time series is a series of data points indexed (or listed or
|
||||
/// graphed) in time order (https://en.wikipedia.org/wiki/Time_series).
|
||||
///
|
||||
/// An instance of this class is exposed as multiple time series during
|
||||
/// scrape, i.e., one time series for each set of labels provided to Add().
|
||||
///
|
||||
/// For example it is possible to collect data for a metric
|
||||
/// `http_requests_total`, with two time series:
|
||||
///
|
||||
/// - all HTTP requests that used the method POST
|
||||
/// - all HTTP requests that used the method GET
|
||||
///
|
||||
/// The metric name specifies the general feature of a system that is
|
||||
/// measured, e.g., `http_requests_total`. Labels enable Prometheus's
|
||||
/// dimensional data model: any given combination of labels for the same
|
||||
/// metric name identifies a particular dimensional instantiation of that
|
||||
/// metric. For example a label for 'all HTTP requests that used the method
|
||||
/// POST' can be assigned with `method= "POST"`.
|
||||
///
|
||||
/// Given a metric name and a set of labels, time series are frequently
|
||||
/// identified using this notation:
|
||||
///
|
||||
/// <metric name> { < label name >= <label value>, ... }
|
||||
///
|
||||
/// It is required to follow the syntax of metric names and labels given by:
|
||||
/// https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels
|
||||
///
|
||||
/// The following metric and label conventions are not required for using
|
||||
/// Prometheus, but can serve as both a style-guide and a collection of best
|
||||
/// practices: https://prometheus.io/docs/practices/naming/
|
||||
///
|
||||
/// \tparam T One of the metric types Counter, Gauge, Histogram or Summary.
|
||||
template <typename T>
|
||||
class PROMETHEUS_CPP_CORE_EXPORT Family : public Collectable {
|
||||
public:
|
||||
/// \brief Create a new metric.
|
||||
///
|
||||
/// Every metric is uniquely identified by its name and a set of key-value
|
||||
/// pairs, also known as labels. Prometheus's query language allows filtering
|
||||
/// and aggregation based on metric name and these labels.
|
||||
///
|
||||
/// This example selects all time series that have the `http_requests_total`
|
||||
/// metric name:
|
||||
///
|
||||
/// http_requests_total
|
||||
///
|
||||
/// It is possible to assign labels to the metric name. These labels are
|
||||
/// propagated to each dimensional data added with Add(). For example if a
|
||||
/// label `job= "prometheus"` is provided to this constructor, it is possible
|
||||
/// to filter this time series with Prometheus's query language by appending
|
||||
/// a set of labels to match in curly braces ({})
|
||||
///
|
||||
/// http_requests_total{job= "prometheus"}
|
||||
///
|
||||
/// For further information see: [Querying Basics]
|
||||
/// (https://prometheus.io/docs/prometheus/latest/querying/basics/)
|
||||
///
|
||||
/// \param name Set the metric name.
|
||||
/// \param help Set an additional description.
|
||||
/// \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 Labels& constant_labels);
|
||||
|
||||
/// \brief Add a new dimensional data.
|
||||
///
|
||||
/// Each new set of labels adds a new dimensional data and is exposed in
|
||||
/// Prometheus as a time series. It is possible to filter the time series
|
||||
/// with Prometheus's query language by appending a set of labels to match in
|
||||
/// curly braces ({})
|
||||
///
|
||||
/// 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 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
|
||||
/// labels already exists - the already existing dimensional data.
|
||||
/// \throw std::runtime_exception on invalid label names.
|
||||
template <typename... Args>
|
||||
T& Add(const Labels& labels, Args&&... args) {
|
||||
return Add(labels, std::make_unique<T>(args...));
|
||||
}
|
||||
|
||||
/// \brief Remove the given dimensional data.
|
||||
///
|
||||
/// \param metric Dimensional data to be removed. The function does nothing,
|
||||
/// 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 Labels& labels) const;
|
||||
|
||||
/// \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 Labels& GetConstantLabels() const;
|
||||
|
||||
/// \brief Returns the current value of each dimensional data.
|
||||
///
|
||||
/// Collect is called by the Registry when collecting metrics.
|
||||
///
|
||||
/// \return Zero or more samples for each dimensional data.
|
||||
std::vector<MetricFamily> Collect() const override;
|
||||
|
||||
private:
|
||||
std::unordered_map<Labels, std::unique_ptr<T>, detail::LabelHasher> metrics_;
|
||||
|
||||
const std::string name_;
|
||||
const std::string help_;
|
||||
const Labels constant_labels_;
|
||||
mutable std::mutex mutex_;
|
||||
|
||||
ClientMetric CollectMetric(const Labels& labels, T* metric) const;
|
||||
T& Add(const Labels& labels, std::unique_ptr<T> object);
|
||||
};
|
||||
|
||||
} // namespace prometheus
|
||||
@@ -0,0 +1,94 @@
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include "prometheus/client_metric.h"
|
||||
#include "prometheus/detail/builder.h" // IWYU pragma: export
|
||||
#include "prometheus/detail/core_export.h"
|
||||
#include "prometheus/metric_type.h"
|
||||
|
||||
namespace prometheus {
|
||||
|
||||
/// \brief A gauge metric to represent a value that can arbitrarily go up and
|
||||
/// down.
|
||||
///
|
||||
/// The class represents the metric type gauge:
|
||||
/// https://prometheus.io/docs/concepts/metric_types/#gauge
|
||||
///
|
||||
/// Gauges are typically used for measured values like temperatures or current
|
||||
/// memory usage, but also "counts" that can go up and down, like the number of
|
||||
/// running processes.
|
||||
///
|
||||
/// The class is thread-safe. No concurrent call to any API of this type causes
|
||||
/// a data race.
|
||||
class PROMETHEUS_CPP_CORE_EXPORT Gauge {
|
||||
public:
|
||||
static const MetricType metric_type{MetricType::Gauge};
|
||||
|
||||
/// \brief Create a gauge that starts at 0.
|
||||
Gauge() = default;
|
||||
|
||||
/// \brief Create a gauge that starts at the given amount.
|
||||
explicit Gauge(double);
|
||||
|
||||
/// \brief Increment the gauge by 1.
|
||||
void Increment();
|
||||
|
||||
/// \brief Increment the gauge by the given amount.
|
||||
void Increment(double);
|
||||
|
||||
/// \brief Decrement the gauge by 1.
|
||||
void Decrement();
|
||||
|
||||
/// \brief Decrement the gauge by the given amount.
|
||||
void Decrement(double);
|
||||
|
||||
/// \brief Set the gauge to the given value.
|
||||
void Set(double);
|
||||
|
||||
/// \brief Set the gauge to the current unix time in seconds.
|
||||
void SetToCurrentTime();
|
||||
|
||||
/// \brief Get the current value of the gauge.
|
||||
double Value() const;
|
||||
|
||||
/// \brief Get the current value of the gauge.
|
||||
///
|
||||
/// Collect is called by the Registry when collecting metrics.
|
||||
ClientMetric Collect() const;
|
||||
|
||||
private:
|
||||
void Change(double);
|
||||
std::atomic<double> value_{0.0};
|
||||
};
|
||||
|
||||
/// \brief Return a builder to configure and register a Gauge metric.
|
||||
///
|
||||
/// @copydetails Family<>::Family()
|
||||
///
|
||||
/// Example usage:
|
||||
///
|
||||
/// \code
|
||||
/// auto registry = std::make_shared<Registry>();
|
||||
/// auto& gauge_family = prometheus::BuildGauge()
|
||||
/// .Name("some_name")
|
||||
/// .Help("Additional description.")
|
||||
/// .Labels({{"key", "value"}})
|
||||
/// .Register(*registry);
|
||||
///
|
||||
/// ...
|
||||
/// \endcode
|
||||
///
|
||||
/// \return An object of unspecified type T, i.e., an implementation detail
|
||||
/// except that it has the following members:
|
||||
///
|
||||
/// - Name(const std::string&) to set the metric name,
|
||||
/// - Help(const std::string&) to set an additional description.
|
||||
/// - 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
|
||||
/// Register(Registry&).
|
||||
PROMETHEUS_CPP_CORE_EXPORT detail::Builder<Gauge> BuildGauge();
|
||||
|
||||
} // namespace prometheus
|
||||
@@ -0,0 +1,109 @@
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include "prometheus/client_metric.h"
|
||||
#include "prometheus/counter.h"
|
||||
#include "prometheus/detail/builder.h" // IWYU pragma: export
|
||||
#include "prometheus/detail/core_export.h"
|
||||
#include "prometheus/gauge.h"
|
||||
#include "prometheus/metric_type.h"
|
||||
|
||||
namespace prometheus {
|
||||
|
||||
/// \brief A histogram metric to represent aggregatable distributions of events.
|
||||
///
|
||||
/// This class represents the metric type histogram:
|
||||
/// https://prometheus.io/docs/concepts/metric_types/#histogram
|
||||
///
|
||||
/// A histogram tracks the number of observations and the sum of the observed
|
||||
/// 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 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.
|
||||
///
|
||||
/// The class is thread-safe. No concurrent call to any API of this type causes
|
||||
/// a data race.
|
||||
class PROMETHEUS_CPP_CORE_EXPORT Histogram {
|
||||
public:
|
||||
using BucketBoundaries = std::vector<double>;
|
||||
|
||||
static const MetricType metric_type{MetricType::Histogram};
|
||||
|
||||
/// \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
|
||||
/// interpreted as a half-open interval [b_n, b_n+1) which defines one bucket.
|
||||
///
|
||||
/// There is no limitation on how the buckets are divided, i.e, equal size,
|
||||
/// exponential etc..
|
||||
///
|
||||
/// The bucket boundaries cannot be changed once the histogram is created.
|
||||
explicit Histogram(const BucketBoundaries& buckets);
|
||||
|
||||
/// \copydoc Histogram::Histogram(const BucketBoundaries&)
|
||||
explicit Histogram(BucketBoundaries&& buckets);
|
||||
|
||||
/// \brief Observe the given amount.
|
||||
///
|
||||
/// The given amount selects the 'observed' bucket. The observed bucket is
|
||||
/// chosen for which the given amount falls into the half-open interval [b_n,
|
||||
/// b_n+1). The counter of the observed bucket is incremented. Also the total
|
||||
/// 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<double>& bucket_increments,
|
||||
double sum_of_values);
|
||||
|
||||
/// \brief Get the current value of the histogram.
|
||||
///
|
||||
/// Collect is called by the Registry when collecting metrics.
|
||||
ClientMetric Collect() const;
|
||||
|
||||
private:
|
||||
BucketBoundaries bucket_boundaries_;
|
||||
mutable std::mutex mutex_;
|
||||
std::vector<Counter> bucket_counts_;
|
||||
Gauge sum_;
|
||||
};
|
||||
|
||||
/// \brief Return a builder to configure and register a Histogram metric.
|
||||
///
|
||||
/// @copydetails Family<>::Family()
|
||||
///
|
||||
/// Example usage:
|
||||
///
|
||||
/// \code
|
||||
/// auto registry = std::make_shared<Registry>();
|
||||
/// auto& histogram_family = prometheus::BuildHistogram()
|
||||
/// .Name("some_name")
|
||||
/// .Help("Additional description.")
|
||||
/// .Labels({{"key", "value"}})
|
||||
/// .Register(*registry);
|
||||
///
|
||||
/// ...
|
||||
/// \endcode
|
||||
///
|
||||
/// \return An object of unspecified type T, i.e., an implementation detail
|
||||
/// except that it has the following members:
|
||||
///
|
||||
/// - Name(const std::string&) to set the metric name,
|
||||
/// - Help(const std::string&) to set an additional description.
|
||||
/// - 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
|
||||
/// Register(Registry&).
|
||||
PROMETHEUS_CPP_CORE_EXPORT detail::Builder<Histogram> BuildHistogram();
|
||||
|
||||
} // namespace prometheus
|
||||
@@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
|
||||
#include "prometheus/client_metric.h"
|
||||
#include "prometheus/detail/builder.h" // IWYU pragma: export
|
||||
#include "prometheus/detail/core_export.h"
|
||||
#include "prometheus/metric_type.h"
|
||||
|
||||
namespace prometheus {
|
||||
|
||||
/// \brief A info metric to represent textual information which should not
|
||||
/// change during process lifetime.
|
||||
///
|
||||
/// This class represents the metric type info:
|
||||
/// https://github.com/OpenObservability/OpenMetrics/blob/98ae26c87b1c3bcf937909a880b32c8be643cc9b/specification/OpenMetrics.md#info
|
||||
|
||||
/// Prometheus does not provide this type directly, it is used by emulating a
|
||||
/// gauge with value 1: https://prometheus.io/docs/concepts/metric_types/#gauge
|
||||
///
|
||||
/// The value of the info cannot change. Example of infos are:
|
||||
/// - the application's version
|
||||
/// - revision control commit
|
||||
/// - version of the compiler
|
||||
///
|
||||
/// The class is thread-safe. No concurrent call to any API of this type causes
|
||||
/// a data race.
|
||||
class PROMETHEUS_CPP_CORE_EXPORT Info {
|
||||
public:
|
||||
static const MetricType metric_type{MetricType::Info};
|
||||
|
||||
/// \brief Create a info.
|
||||
Info() = default;
|
||||
|
||||
/// \brief Get the current value of the info.
|
||||
///
|
||||
/// Collect is called by the Registry when collecting metrics.
|
||||
ClientMetric Collect() const;
|
||||
};
|
||||
|
||||
/// \brief Return a builder to configure and register a Info metric.
|
||||
///
|
||||
/// @copydetails Family<>::Family()
|
||||
///
|
||||
/// Example usage:
|
||||
///
|
||||
/// \code
|
||||
/// auto registry = std::make_shared<Registry>();
|
||||
/// auto& info_family = prometheus::BuildInfo()
|
||||
/// .Name("some_name")
|
||||
/// .Help("Additional description.")
|
||||
/// .Labels({{"key", "value"}})
|
||||
/// .Register(*registry);
|
||||
///
|
||||
/// ...
|
||||
/// \endcode
|
||||
///
|
||||
/// \return An object of unspecified type T, i.e., an implementation detail
|
||||
/// except that it has the following members:
|
||||
///
|
||||
/// - Name(const std::string&) to set the metric name,
|
||||
/// - Help(const std::string&) to set an additional description.
|
||||
/// - Labels(const Labels&) to assign a set of
|
||||
/// key-value pairs (= labels) to the metric.
|
||||
///
|
||||
/// To finish the configuration of the Info metric, register it with
|
||||
/// Register(Registry&).
|
||||
PROMETHEUS_CPP_CORE_EXPORT detail::Builder<Info> BuildInfo();
|
||||
|
||||
} // namespace prometheus
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace prometheus {
|
||||
|
||||
/// \brief Multiple labels and their value.
|
||||
using Labels = std::map<std::string, std::string>;
|
||||
|
||||
} // namespace prometheus
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "prometheus/client_metric.h"
|
||||
#include "prometheus/detail/core_export.h"
|
||||
#include "prometheus/metric_type.h"
|
||||
|
||||
namespace prometheus {
|
||||
|
||||
struct PROMETHEUS_CPP_CORE_EXPORT MetricFamily {
|
||||
std::string name;
|
||||
std::string help;
|
||||
MetricType type = MetricType::Untyped;
|
||||
std::vector<ClientMetric> metric;
|
||||
};
|
||||
} // namespace prometheus
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
namespace prometheus {
|
||||
|
||||
enum class MetricType {
|
||||
Counter,
|
||||
Gauge,
|
||||
Summary,
|
||||
Untyped,
|
||||
Histogram,
|
||||
Info,
|
||||
};
|
||||
|
||||
} // namespace prometheus
|
||||
@@ -0,0 +1,120 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#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 {
|
||||
|
||||
class Counter;
|
||||
class Gauge;
|
||||
class Histogram;
|
||||
class Info;
|
||||
class Summary;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename T>
|
||||
class Builder; // IWYU pragma: keep
|
||||
|
||||
}
|
||||
/// \brief Manages the collection of a number of metrics.
|
||||
///
|
||||
/// The Registry is responsible to expose data to a class/method/function
|
||||
/// "bridge", which returns the metrics in a format Prometheus supports.
|
||||
///
|
||||
/// The key class is the Collectable. This has a method - called Collect() -
|
||||
/// that returns zero or more metrics and their samples. The metrics are
|
||||
/// represented by the class Family<>, which implements the Collectable
|
||||
/// interface. A new metric is registered with BuildCounter(), BuildGauge(),
|
||||
/// BuildHistogram(), BuildInfo() or BuildSummary().
|
||||
///
|
||||
/// The class is thread-safe. No concurrent call to any API of this type causes
|
||||
/// 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 name Create a new registry.
|
||||
///
|
||||
/// \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;
|
||||
|
||||
/// \brief Returns a list of metrics and their samples.
|
||||
///
|
||||
/// Every time the Registry is scraped it calls each of the metrics Collect
|
||||
/// function.
|
||||
///
|
||||
/// \return Zero or more metrics and their samples.
|
||||
std::vector<MetricFamily> 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 <typename T>
|
||||
bool Remove(const Family<T>& family);
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
friend class detail::Builder;
|
||||
|
||||
template <typename T>
|
||||
std::vector<std::unique_ptr<Family<T>>>& GetFamilies();
|
||||
|
||||
template <typename T>
|
||||
bool NameExistsInOtherType(const std::string& name) const;
|
||||
|
||||
template <typename T>
|
||||
Family<T>& Add(const std::string& name, const std::string& help,
|
||||
const Labels& labels);
|
||||
|
||||
const InsertBehavior insert_behavior_;
|
||||
std::vector<std::unique_ptr<Family<Counter>>> counters_;
|
||||
std::vector<std::unique_ptr<Family<Gauge>>> gauges_;
|
||||
std::vector<std::unique_ptr<Family<Histogram>>> histograms_;
|
||||
std::vector<std::unique_ptr<Family<Info>>> infos_;
|
||||
std::vector<std::unique_ptr<Family<Summary>>> summaries_;
|
||||
mutable std::mutex mutex_;
|
||||
};
|
||||
|
||||
} // namespace prometheus
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "prometheus/detail/core_export.h"
|
||||
#include "prometheus/metric_family.h"
|
||||
|
||||
namespace prometheus {
|
||||
|
||||
class PROMETHEUS_CPP_CORE_EXPORT Serializer {
|
||||
public:
|
||||
virtual ~Serializer() = default;
|
||||
virtual std::string Serialize(const std::vector<MetricFamily>&) const;
|
||||
virtual void Serialize(std::ostream& out,
|
||||
const std::vector<MetricFamily>& metrics) const = 0;
|
||||
};
|
||||
|
||||
} // namespace prometheus
|
||||
@@ -0,0 +1,128 @@
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include "prometheus/client_metric.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"
|
||||
#include "prometheus/metric_type.h"
|
||||
|
||||
namespace prometheus {
|
||||
|
||||
/// \brief A summary metric samples observations over a sliding window of time.
|
||||
///
|
||||
/// This class represents the metric type summary:
|
||||
/// https://prometheus.io/docs/instrumenting/writing_clientlibs/#summary
|
||||
///
|
||||
/// A summary provides a total count of observations and a sum of all observed
|
||||
/// values. In contrast to a histogram metric it also calculates configurable
|
||||
/// Phi-quantiles over a sliding window of time.
|
||||
///
|
||||
/// The essential difference between summaries and histograms is that summaries
|
||||
/// calculate streaming Phi-quantiles on the client side and expose them
|
||||
/// directly, while histograms expose bucketed observation counts and the
|
||||
/// calculation of quantiles from the buckets of a histogram happens on the
|
||||
/// server side:
|
||||
/// https://prometheus.io/docs/prometheus/latest/querying/functions/#histogram_quantile.
|
||||
///
|
||||
/// Note that Phi designates the probability density function of the standard
|
||||
/// Gaussian distribution.
|
||||
///
|
||||
/// See https://prometheus.io/docs/practices/histograms/ for detailed
|
||||
/// explanations of Phi-quantiles, summary usage, and differences to histograms.
|
||||
///
|
||||
/// The class is thread-safe. No concurrent call to any API of this type causes
|
||||
/// a data race.
|
||||
class PROMETHEUS_CPP_CORE_EXPORT Summary {
|
||||
public:
|
||||
using Quantiles = std::vector<detail::CKMSQuantiles::Quantile>;
|
||||
|
||||
static const MetricType metric_type{MetricType::Summary};
|
||||
|
||||
/// \brief Create a summary metric.
|
||||
///
|
||||
/// \param quantiles A list of 'targeted' Phi-quantiles. A targeted
|
||||
/// Phi-quantile is specified in the form of a Phi-quantile and tolerated
|
||||
/// error. For example a Quantile{0.5, 0.1} means that the median (= 50th
|
||||
/// percentile) should be returned with 10 percent error or a Quantile{0.2,
|
||||
/// 0.05} means the 20th percentile with 5 percent tolerated error. Note that
|
||||
/// percentiles and quantiles are the same concept, except percentiles are
|
||||
/// expressed as percentages. The Phi-quantile must be in the interval [0, 1].
|
||||
/// Note that a lower tolerated error for a Phi-quantile results in higher
|
||||
/// usage of resources (memory and cpu) to calculate the summary.
|
||||
///
|
||||
/// The Phi-quantiles are calculated over a sliding window of time. The
|
||||
/// sliding window of time is configured by max_age and age_buckets.
|
||||
///
|
||||
/// \param max_age Set the duration of the time window, i.e., how long
|
||||
/// observations are kept before they are discarded. The default value is 60
|
||||
/// seconds.
|
||||
///
|
||||
/// \param age_buckets Set the number of buckets of the time window. It
|
||||
/// determines the number of buckets used to exclude observations that are
|
||||
/// older than max_age from the summary, e.g., if max_age is 60 seconds and
|
||||
/// age_buckets is 5, buckets will be switched every 12 seconds. The value is
|
||||
/// a trade-off between resources (memory and cpu for maintaining the bucket)
|
||||
/// and how smooth the time window is moved. With only one age bucket it
|
||||
/// effectively results in a complete reset of the summary each time max_age
|
||||
/// has passed. The default value is 5.
|
||||
explicit Summary(const Quantiles& quantiles,
|
||||
std::chrono::milliseconds max_age = std::chrono::seconds{60},
|
||||
int age_buckets = 5);
|
||||
|
||||
/// \copydoc Summary::Summary(const Quantiles&,std::chrono::milliseconds,int)
|
||||
explicit Summary(Quantiles&& quantiles,
|
||||
std::chrono::milliseconds max_age = std::chrono::seconds{60},
|
||||
int age_buckets = 5);
|
||||
|
||||
/// \brief Observe the given amount.
|
||||
void Observe(double value);
|
||||
|
||||
/// \brief Get the current value of the summary.
|
||||
///
|
||||
/// Collect is called by the Registry when collecting metrics.
|
||||
ClientMetric Collect() const;
|
||||
|
||||
private:
|
||||
Quantiles quantiles_;
|
||||
mutable std::mutex mutex_;
|
||||
std::uint64_t count_{};
|
||||
double sum_{};
|
||||
detail::TimeWindowQuantiles quantile_values_;
|
||||
};
|
||||
|
||||
/// \brief Return a builder to configure and register a Summary metric.
|
||||
///
|
||||
/// @copydetails Family<>::Family()
|
||||
///
|
||||
/// Example usage:
|
||||
///
|
||||
/// \code
|
||||
/// auto registry = std::make_shared<Registry>();
|
||||
/// auto& summary_family = prometheus::BuildSummary()
|
||||
/// .Name("some_name")
|
||||
/// .Help("Additional description.")
|
||||
/// .Labels({{"key", "value"}})
|
||||
/// .Register(*registry);
|
||||
///
|
||||
/// ...
|
||||
/// \endcode
|
||||
///
|
||||
/// \return An object of unspecified type T, i.e., an implementation detail
|
||||
/// except that it has the following members:
|
||||
///
|
||||
/// - Name(const std::string&) to set the metric name,
|
||||
/// - Help(const std::string&) to set an additional description.
|
||||
/// - 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
|
||||
/// Register(Registry&).
|
||||
PROMETHEUS_CPP_CORE_EXPORT detail::Builder<Summary> BuildSummary();
|
||||
|
||||
} // namespace prometheus
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <iosfwd>
|
||||
#include <vector>
|
||||
|
||||
#include "prometheus/detail/core_export.h"
|
||||
#include "prometheus/metric_family.h"
|
||||
#include "prometheus/serializer.h"
|
||||
|
||||
namespace prometheus {
|
||||
|
||||
class PROMETHEUS_CPP_CORE_EXPORT TextSerializer : public Serializer {
|
||||
public:
|
||||
using Serializer::Serialize;
|
||||
void Serialize(std::ostream& out,
|
||||
const std::vector<MetricFamily>& metrics) const override;
|
||||
};
|
||||
|
||||
} // namespace prometheus
|
||||
@@ -0,0 +1,85 @@
|
||||
|
||||
#include "prometheus/check_names.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
namespace prometheus {
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
/// \param type metric type
|
||||
/// \return true is valid, false otherwise
|
||||
bool CheckLabelName(const std::string& name, MetricType type) {
|
||||
if (!nameStartsValid(name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto validLabelCharacters = [](char c) {
|
||||
return isLocaleIndependentAlphaNumeric(c) || c == '_';
|
||||
};
|
||||
|
||||
if ((type == MetricType::Histogram && name == "le") ||
|
||||
(type == MetricType::Summary && name == "quantile")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto mismatch =
|
||||
std::find_if_not(std::begin(name), std::end(name), validLabelCharacters);
|
||||
return mismatch == std::end(name);
|
||||
}
|
||||
} // namespace prometheus
|
||||
@@ -0,0 +1,22 @@
|
||||
#include "prometheus/counter.h"
|
||||
|
||||
namespace prometheus {
|
||||
|
||||
void Counter::Increment() { gauge_.Increment(); }
|
||||
|
||||
void Counter::Increment(const double val) {
|
||||
if (val < 0.0) {
|
||||
return;
|
||||
}
|
||||
gauge_.Increment(val);
|
||||
}
|
||||
|
||||
double Counter::Value() const { return gauge_.Value(); }
|
||||
|
||||
ClientMetric Counter::Collect() const {
|
||||
ClientMetric metric;
|
||||
metric.counter.value = Value();
|
||||
return metric;
|
||||
}
|
||||
|
||||
} // namespace prometheus
|
||||
@@ -0,0 +1,52 @@
|
||||
#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/info.h"
|
||||
#include "prometheus/registry.h"
|
||||
#include "prometheus/summary.h"
|
||||
|
||||
namespace prometheus {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename T>
|
||||
Builder<T>& Builder<T>::Labels(const ::prometheus::Labels& labels) {
|
||||
labels_ = labels;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Builder<T>& Builder<T>::Name(const std::string& name) {
|
||||
name_ = name;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Builder<T>& Builder<T>::Help(const std::string& help) {
|
||||
help_ = help;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Family<T>& Builder<T>::Register(Registry& registry) {
|
||||
return registry.Add<T>(name_, help_, labels_);
|
||||
}
|
||||
|
||||
template class PROMETHEUS_CPP_CORE_EXPORT Builder<Counter>;
|
||||
template class PROMETHEUS_CPP_CORE_EXPORT Builder<Gauge>;
|
||||
template class PROMETHEUS_CPP_CORE_EXPORT Builder<Histogram>;
|
||||
template class PROMETHEUS_CPP_CORE_EXPORT Builder<Info>;
|
||||
template class PROMETHEUS_CPP_CORE_EXPORT Builder<Summary>;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
detail::Builder<Counter> BuildCounter() { return {}; }
|
||||
detail::Builder<Gauge> BuildGauge() { return {}; }
|
||||
detail::Builder<Histogram> BuildHistogram() { return {}; }
|
||||
detail::Builder<Info> BuildInfo() { return {}; }
|
||||
detail::Builder<Summary> BuildSummary() { return {}; }
|
||||
|
||||
} // namespace prometheus
|
||||
@@ -0,0 +1,153 @@
|
||||
#include "prometheus/detail/ckms_quantiles.h" // IWYU pragma: export
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
|
||||
namespace prometheus {
|
||||
namespace detail {
|
||||
|
||||
CKMSQuantiles::Quantile::Quantile(double quantile, double error)
|
||||
: quantile(quantile),
|
||||
error(error),
|
||||
u(2.0 * error / (1.0 - quantile)),
|
||||
v(2.0 * error / quantile) {}
|
||||
|
||||
CKMSQuantiles::Item::Item(double value, int lower_delta, int delta)
|
||||
: value(value), g(lower_delta), delta(delta) {}
|
||||
|
||||
CKMSQuantiles::CKMSQuantiles(const std::vector<Quantile>& quantiles)
|
||||
: quantiles_(quantiles), count_(0), buffer_{}, buffer_count_(0) {}
|
||||
|
||||
void CKMSQuantiles::insert(double value) {
|
||||
buffer_[buffer_count_] = value;
|
||||
++buffer_count_;
|
||||
|
||||
if (buffer_count_ == buffer_.size()) {
|
||||
insertBatch();
|
||||
compress();
|
||||
}
|
||||
}
|
||||
|
||||
double CKMSQuantiles::get(double q) {
|
||||
insertBatch();
|
||||
compress();
|
||||
|
||||
if (sample_.empty()) {
|
||||
return std::numeric_limits<double>::quiet_NaN();
|
||||
}
|
||||
|
||||
int rankMin = 0;
|
||||
const auto desired = static_cast<int>(q * count_);
|
||||
const auto bound = desired + (allowableError(desired) / 2);
|
||||
|
||||
auto it = sample_.begin();
|
||||
decltype(it) prev;
|
||||
auto cur = it++;
|
||||
|
||||
while (it != sample_.end()) {
|
||||
prev = cur;
|
||||
cur = it++;
|
||||
|
||||
rankMin += prev->g;
|
||||
|
||||
if (rankMin + cur->g + cur->delta > bound) {
|
||||
return prev->value;
|
||||
}
|
||||
}
|
||||
|
||||
return sample_.back().value;
|
||||
}
|
||||
|
||||
void CKMSQuantiles::reset() {
|
||||
count_ = 0;
|
||||
sample_.clear();
|
||||
buffer_count_ = 0;
|
||||
}
|
||||
|
||||
double CKMSQuantiles::allowableError(int rank) {
|
||||
auto size = sample_.size();
|
||||
double minError = size + 1;
|
||||
|
||||
for (const auto& q : quantiles_.get()) {
|
||||
double error;
|
||||
if (rank <= q.quantile * size) {
|
||||
error = q.u * (size - rank);
|
||||
} else {
|
||||
error = q.v * rank;
|
||||
}
|
||||
if (error < minError) {
|
||||
minError = error;
|
||||
}
|
||||
}
|
||||
|
||||
return minError;
|
||||
}
|
||||
|
||||
bool CKMSQuantiles::insertBatch() {
|
||||
if (buffer_count_ == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::sort(buffer_.begin(), buffer_.begin() + buffer_count_);
|
||||
|
||||
std::size_t start = 0;
|
||||
if (sample_.empty()) {
|
||||
sample_.emplace_back(buffer_[0], 1, 0);
|
||||
++start;
|
||||
++count_;
|
||||
}
|
||||
|
||||
std::size_t idx = 0;
|
||||
std::size_t item = idx++;
|
||||
|
||||
for (std::size_t i = start; i < buffer_count_; ++i) {
|
||||
double v = buffer_[i];
|
||||
while (idx < sample_.size() && sample_[item].value < v) {
|
||||
item = idx++;
|
||||
}
|
||||
|
||||
if (sample_[item].value > v) {
|
||||
--idx;
|
||||
}
|
||||
|
||||
int delta;
|
||||
if (idx - 1 == 0 || idx + 1 == sample_.size()) {
|
||||
delta = 0;
|
||||
} else {
|
||||
delta = static_cast<int>(std::floor(allowableError(idx + 1))) + 1;
|
||||
}
|
||||
|
||||
sample_.emplace(sample_.begin() + idx, v, 1, delta);
|
||||
count_++;
|
||||
item = idx++;
|
||||
}
|
||||
|
||||
buffer_count_ = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CKMSQuantiles::compress() {
|
||||
if (sample_.size() < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::size_t idx = 0;
|
||||
std::size_t prev;
|
||||
std::size_t next = idx++;
|
||||
|
||||
while (idx < sample_.size()) {
|
||||
prev = next;
|
||||
next = idx++;
|
||||
|
||||
if (sample_[prev].g + sample_[next].g + sample_[next].delta <=
|
||||
allowableError(idx - 1)) {
|
||||
sample_[next].g += sample_[prev].g;
|
||||
sample_.erase(sample_.begin() + prev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace prometheus
|
||||
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
|
||||
namespace prometheus {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/// \brief Combine a hash value with nothing.
|
||||
/// It's the boundary condition of this serial functions.
|
||||
///
|
||||
/// \param seed Not effect.
|
||||
inline void hash_combine(std::size_t*) {}
|
||||
|
||||
/// \brief Combine the given hash value with another object.
|
||||
///
|
||||
/// \param seed The given hash value. It's a input/output parameter.
|
||||
/// \param value The object that will be combined with the given hash value.
|
||||
template <typename T>
|
||||
inline void hash_combine(std::size_t* seed, const T& value) {
|
||||
*seed ^= std::hash<T>{}(value) + 0x9e3779b9 + (*seed << 6) + (*seed >> 2);
|
||||
}
|
||||
|
||||
/// \brief Combine the given hash value with another objects. It's a recursion。
|
||||
///
|
||||
/// \param seed The give hash value. It's a input/output parameter.
|
||||
/// \param value The object that will be combined with the given hash value.
|
||||
/// \param args The objects that will be combined with the given hash value.
|
||||
template <typename T, typename... Types>
|
||||
inline void hash_combine(std::size_t* seed, const T& value,
|
||||
const Types&... args) {
|
||||
hash_combine(seed, value);
|
||||
hash_combine(seed, args...);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace prometheus
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user