1 # Prometheus Client Library for Modern C++
3 [![CI Status](https://github.com/jupp0r/prometheus-cpp/workflows/Continuous%20Integration/badge.svg)](https://github.com/jupp0r/prometheus-cpp/actions?workflow=Continuous+Integration)
4 [![Travis Status](https://travis-ci.org/jupp0r/prometheus-cpp.svg?branch=master)](https://travis-ci.org/jupp0r/prometheus-cpp)
5 [![Coverage Status](https://coveralls.io/repos/github/jupp0r/prometheus-cpp/badge.svg?branch=master)](https://coveralls.io/github/jupp0r/prometheus-cpp?branch=master)
6 [![Coverity Scan](https://scan.coverity.com/projects/10567/badge.svg)](https://scan.coverity.com/projects/jupp0r-prometheus-cpp)
8 This library aims to enable
9 [Metrics-Driven Development](https://sookocheff.com/post/mdd/mdd/) for
10 C++ services. It implements the
11 [Prometheus Data Model](https://prometheus.io/docs/concepts/data_model/),
12 a powerful abstraction on which to collect and expose metrics. We
13 offer the possibility for metrics to be collected by Prometheus, but
14 other push/pull collections can be added as plugins.
18 See https://jupp0r.github.io/prometheus-cpp for more detailed interface documentation.
21 #include <prometheus/counter.h>
22 #include <prometheus/exposer.h>
23 #include <prometheus/registry.h>
33 using namespace prometheus;
35 // create an http server running on port 8080
36 Exposer exposer{"127.0.0.1:8080"};
38 // create a metrics registry
39 // @note it's the users responsibility to keep the object alive
40 auto registry = std::make_shared<Registry>();
42 // add a new counter family to the registry (families combine values with the
43 // same name, but distinct label dimensions)
45 // @note please follow the metric-naming best-practices:
46 // https://prometheus.io/docs/practices/naming/
47 auto& packet_counter = BuildCounter()
48 .Name("observed_packets_total")
49 .Help("Number of observed packets")
52 // add and remember dimensional data, incrementing those is very cheap
53 auto& tcp_rx_counter =
54 packet_counter.Add({{"protocol", "tcp"}, {"direction", "rx"}});
55 auto& tcp_tx_counter =
56 packet_counter.Add({{"protocol", "tcp"}, {"direction", "tx"}});
57 auto& udp_rx_counter =
58 packet_counter.Add({{"protocol", "udp"}, {"direction", "rx"}});
59 auto& udp_tx_counter =
60 packet_counter.Add({{"protocol", "udp"}, {"direction", "tx"}});
62 // add a counter whose dimensional data is not known at compile time
63 // nevertheless dimensional values should only occur in low cardinality:
64 // https://prometheus.io/docs/practices/naming/#labels
65 auto& http_requests_counter = BuildCounter()
66 .Name("http_requests_total")
67 .Help("Number of HTTP requests")
70 // ask the exposer to scrape the registry on incoming HTTP requests
71 exposer.RegisterCollectable(registry);
74 std::this_thread::sleep_for(std::chrono::seconds(1));
75 const auto random_value = std::rand();
77 if (random_value & 1) tcp_rx_counter.Increment();
78 if (random_value & 2) tcp_tx_counter.Increment();
79 if (random_value & 4) udp_rx_counter.Increment();
80 if (random_value & 8) udp_tx_counter.Increment();
82 const std::array<std::string, 4> methods = {"GET", "PUT", "POST", "HEAD"};
83 auto method = methods.at(random_value % methods.size());
84 // dynamically calling Family<T>.Add() works but is slow and should be
86 http_requests_counter.Add({{"method", method}}).Increment();
95 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).
99 There are two supported ways to build
100 `prometheus-cpp` - [CMake](https://cmake.org)
101 and [bazel](https://bazel.io). Both are tested in CI and should work
102 on master and for all releases.
104 In case these instructions don't work for you, looking at
105 the [GitHub Workflows](.github/workflows) might help.
109 For CMake builds don't forget to fetch the submodules first. Please note that
110 [zlib](https://zlib.net/) and [libcurl](https://curl.se/) are not provided by
111 the included submodules. In the example below their usage is disabled.
116 # fetch third-party dependencies
124 cmake .. -DBUILD_SHARED_LIBS=ON -DENABLE_PUSH=OFF -DENABLE_COMPRESSION=OFF
127 cmake --build . --parallel 4
132 # install the libraries and headers
138 Install [bazel](https://www.bazel.io). Bazel makes it easy to add
139 this repo to your project as a dependency. Just add the following
143 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file")
145 name = "com_github_jupp0r_prometheus_cpp",
146 strip_prefix = "prometheus-cpp-master",
147 urls = ["https://github.com/jupp0r/prometheus-cpp/archive/master.zip"],
150 load("@com_github_jupp0r_prometheus_cpp//bazel:repositories.bzl", "prometheus_cpp_repositories")
152 prometheus_cpp_repositories()
155 Then, you can reference this library in your own `BUILD` file, as
156 demonstrated with the sample server included in this repository:
160 name = "sample_server",
161 srcs = ["sample_server.cc"],
162 deps = ["@com_github_jupp0r_prometheus_cpp//pull"],
166 When you call `prometheus_cpp_repositories()` in your `WORKSPACE` file,
167 you load the following dependencies, if they do not exist yet, into your project:
169 * `civetweb` for [Civetweb](https://github.com/civetweb/civetweb)
170 * `com_google_googletest` for [Google Test](https://github.com/google/googletest)
171 * `com_github_google_benchmark` for [Google Benchmark](https://github.com/google/benchmark)
172 * `com_github_curl` for [curl](https://curl.haxx.se/)
173 * `net_zlib_zlib` for [zlib](http://www.zlib.net/)
175 The list of dependencies is also available from file [repositories.bzl](bazel/repositories.bzl).
179 By configuring CPack you can generate an installer like a
180 Debian package (.deb) or RPM (.rpm) for the static or dynamic
181 libraries so they can be easily installed on
184 Please refer to the [CPack](https://cmake.org/cmake/help/latest/module/CPack.html)
185 documentation for all available generators and their
186 configuration options.
188 To generate a Debian package you could follow these steps:
191 # fetch third-party dependencies
192 git submodule update --init
195 cmake -B_build -DCPACK_GENERATOR=DEB -DBUILD_SHARED_LIBS=ON # or OFF for static libraries
198 cmake --build _build --target package --parallel $(nproc)
201 This will place an appropriately named .deb in the
202 `_build` folder. To build a RPM package set the `CPACK_GENERATOR`
205 ## Consuming the installed project
209 Consuming prometheus-cpp via CMake is the preferred way because all the dependencies
210 between the three prometheus-cpp libraries are handled correctly.
212 The `cmake/project-import` directory contains an
213 example project and minimal [CMakeLists.txt](cmake/project-import-cmake/CMakeLists.txt).
217 The [vcpkg](https://github.com/microsoft/vcpkg) package manager contains a
218 prometheus-cpp port which has been tested on Linux, macOS, and Windows.
222 [Conan](https://conan.io/) package manager contains prometheus-cpp package as well
223 in [ConanCenter](https://conan.io/center/prometheus-cpp) repository
227 When manually linking prometheus-cpp the library order matters. The needed
228 libraries depend on the individual use case but the following should work for the pull metrics approach:
231 -lprometheus-cpp-pull -lprometheus-cpp-core -lz
234 For the push-workflow please try:
237 -lprometheus-cpp-push -lprometheus-cpp-core -lcurl -lz
242 Please adhere to the [Google C++ Style
243 Guide](https://google.github.io/styleguide/cppguide.html). Make sure
244 to clang-format your patches before opening a PR. Also make sure to
245 adhere to [these commit message
246 guidelines](https://chris.beams.io/posts/git-commit/).
248 You can check out this repo and build the library using
250 bazel build //... # build everything
251 bazel build //core //pull # build just the libraries
254 Run the unit tests using
259 There is also an integration test that
260 uses [telegraf](https://github.com/influxdata/telegraf) to scrape a
261 sample server. With telegraf installed, it can be run using
263 bazel test //pull/tests/integration:scrape-test
268 There's a benchmark suite you can run:
271 bazel run -c opt //core/benchmarks
273 INFO: Analysed target //core/benchmarks:benchmarks (0 packages loaded, 0 targets configured).
274 INFO: Found 1 target...
275 Target //core/benchmarks:benchmarks up-to-date:
276 bazel-bin/core/benchmarks/benchmarks
277 INFO: Elapsed time: 0.356s, Critical Path: 0.01s, Remote (0.00% of the time): [queue: 0.00%, setup: 0.00%, process: 0.00%]
279 INFO: Build completed successfully, 1 total action
280 INFO: Build completed successfully, 1 total action
282 Run on (4 X 2200 MHz CPU s)
285 L1 Instruction 32K (x2)
287 L3 Unified 4194K (x1)
288 -----------------------------------------------------------------------------------
289 Benchmark Time CPU Iterations
290 -----------------------------------------------------------------------------------
291 BM_Counter_Increment 13 ns 12 ns 55616469
292 BM_Counter_Collect 7 ns 7 ns 99823170
293 BM_Gauge_Increment 12 ns 12 ns 51511873
294 BM_Gauge_Decrement 12 ns 12 ns 56831098
295 BM_Gauge_SetToCurrentTime 184 ns 183 ns 3928964
296 BM_Gauge_Collect 6 ns 6 ns 117223478
297 BM_Histogram_Observe/0 134 ns 124 ns 5665310
298 BM_Histogram_Observe/1 122 ns 120 ns 5937185
299 BM_Histogram_Observe/8 137 ns 135 ns 4652863
300 BM_Histogram_Observe/64 143 ns 143 ns 4835957
301 BM_Histogram_Observe/512 259 ns 257 ns 2334750
302 BM_Histogram_Observe/4096 1545 ns 1393 ns 620754
303 BM_Histogram_Collect/0 103 ns 102 ns 5654829
304 BM_Histogram_Collect/1 100 ns 100 ns 7015153
305 BM_Histogram_Collect/8 608 ns 601 ns 1149652
306 BM_Histogram_Collect/64 1438 ns 1427 ns 515236
307 BM_Histogram_Collect/512 5178 ns 5159 ns 114619
308 BM_Histogram_Collect/4096 33527 ns 33280 ns 20785
309 BM_Registry_CreateFamily 320 ns 316 ns 2021567
310 BM_Registry_CreateCounter/0 128 ns 128 ns 5487140
311 BM_Registry_CreateCounter/1 2066 ns 2058 ns 386002
312 BM_Registry_CreateCounter/8 7672 ns 7634 ns 91328
313 BM_Registry_CreateCounter/64 63270 ns 62761 ns 10780
314 BM_Registry_CreateCounter/512 560714 ns 558328 ns 1176
315 BM_Registry_CreateCounter/4096 18672798 ns 18383000 ns 35
316 BM_Summary_Observe/0/iterations:262144 9351 ns 9305 ns 262144
317 BM_Summary_Observe/1/iterations:262144 9242 ns 9169 ns 262144
318 BM_Summary_Observe/8/iterations:262144 14344 ns 14195 ns 262144
319 BM_Summary_Observe/64/iterations:262144 19176 ns 18950 ns 262144
320 BM_Summary_Collect/0/0 31 ns 30 ns 24873766
321 BM_Summary_Collect/1/0 166 ns 166 ns 4266706
322 BM_Summary_Collect/8/0 1040 ns 1036 ns 660527
323 BM_Summary_Collect/64/0 4529 ns 4489 ns 155600
324 BM_Summary_Collect/0/1 28 ns 28 ns 24866697
325 BM_Summary_Collect/1/1 190 ns 188 ns 3930354
326 BM_Summary_Collect/8/1 1372 ns 1355 ns 535779
327 BM_Summary_Collect/64/1 9901 ns 9822 ns 64632
328 BM_Summary_Collect/0/8 29 ns 29 ns 24922651
329 BM_Summary_Collect/1/8 217 ns 215 ns 3278381
330 BM_Summary_Collect/8/8 2275 ns 2256 ns 282503
331 BM_Summary_Collect/64/8 56790 ns 55804 ns 13878
332 BM_Summary_Collect/0/64 32 ns 31 ns 22548350
333 BM_Summary_Collect/1/64 395 ns 389 ns 1817073
334 BM_Summary_Collect/8/64 10187 ns 10064 ns 71928
335 BM_Summary_Collect/64/64 374835 ns 373560 ns 1812
336 BM_Summary_Collect/0/512 28 ns 28 ns 25234228
337 BM_Summary_Collect/1/512 1710 ns 1639 ns 802285
338 BM_Summary_Collect/8/512 50355 ns 49335 ns 15975
339 BM_Summary_Collect/64/512 2520972 ns 2493417 ns 295
340 BM_Summary_Collect/0/4096 31 ns 31 ns 24059034
341 BM_Summary_Collect/1/4096 2719 ns 2698 ns 286186
342 BM_Summary_Collect/8/4096 121689 ns 119995 ns 5647
343 BM_Summary_Collect/64/4096 5660131 ns 5587634 ns 134
344 BM_Summary_Collect/0/32768 29 ns 29 ns 22217567
345 BM_Summary_Collect/1/32768 4344 ns 4294 ns 138135
346 BM_Summary_Collect/8/32768 331563 ns 326403 ns 2017
347 BM_Summary_Collect/64/32768 16363553 ns 16038182 ns 44
348 BM_Summary_Collect/0/262144 27 ns 27 ns 23923036
349 BM_Summary_Collect/1/262144 10457 ns 10332 ns 67690
350 BM_Summary_Collect/8/262144 930434 ns 869234 ns 792
351 BM_Summary_Collect/64/262144 39217069 ns 39054846 ns 13
352 BM_Summary_Observe_Common/iterations:262144 5587 ns 5557 ns 262144
353 BM_Summary_Collect_Common/0 676 ns 673 ns 1054630
354 BM_Summary_Collect_Common/1 709 ns 705 ns 990659
355 BM_Summary_Collect_Common/8 1030 ns 1025 ns 685649
356 BM_Summary_Collect_Common/64 2066 ns 2055 ns 339969
357 BM_Summary_Collect_Common/512 5754 ns 5248 ns 156895
358 BM_Summary_Collect_Common/4096 23894 ns 23292 ns 31096
359 BM_Summary_Collect_Common/32768 49831 ns 49292 ns 13492
360 BM_Summary_Collect_Common/262144 128723 ns 126987 ns 5579
364 Stable and used in production.
366 Parts of the library are instrumented by itself
367 (bytes scraped, number of scrapes, scrape request latencies). There
368 is a working [example](pull/tests/integration/sample_server.cc) that's
369 scraped by telegraf as part of integration tests.
373 ### What scrape formats do you support
375 Only the [Prometheus Text Exposition
376 Format](https://github.com/prometheus/docs/blob/master/content/docs/instrumenting/exposition_formats.md#text-format-details).
377 Support for the protobuf format was removed because it's been removed