Skip to content

Commit f1ec38c

Browse files
committed
Update README.md
Add more information to project description
1 parent c6002a4 commit f1ec38c

File tree

1 file changed

+190
-12
lines changed

1 file changed

+190
-12
lines changed

README.md

Lines changed: 190 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,201 @@
1-
# Prometheus C++ header-only client library
1+
# C++ Header-only Prometheus client library
22

3-
This is a lite, C++ header-only client library for prometheus based on [jupp0r/prometheus-cpp](https://github.com/jupp0r/prometheus-cpp) project.
3+
It is a tool for quickly adding metrics (and profiling) functionality to C++ projects.
44

5-
To see how this can be used see the examples folders.
5+
## Advantages:
66

7-
## Why I decided to do this deep refactoring of an original project prometheus-cpp:
7+
1. Written in pure C++,
8+
2. Header-only,
9+
2. Cross-platform,
10+
3. Compiles with C ++ 11, C ++ 14, C ++ 17 standards,
11+
4. Has no third-party dependencies,
12+
5. Several APIs for use in your projects,
13+
6. Saving metrics to a file (and then works with node_exporter) or sending via http (uses built-in header-only http-client-lite library),
14+
7. Possiblity to use different types for storing metrics data (default is uint32_t, but you can use double or uint64_t types if you want),
15+
8. Five types of metrics are supported: counter, gauge, summary, histogram and benchmark,
16+
10. Has detailed examples of use (see examples folder)
17+
18+
## How it differs from the [jupp0r/prometheus-cpp](https://github.com/jupp0r/prometheus-cpp) project:
819
1. I need a simple header only wariant library without dependencies to write metrics to a .prom file,
920
2. I need the fastest possible work using integer values of counters (original project use only floating pointer values),
1021
3. The origianl project have problems on compilers that do not know how to do LTO optimization,
1122
4. I did not like the python style of the original project and the large amount of extra code in it and I wanted to make it lighter and more c++ classic.
1223

13-
## Now the core of the library has been rewritten:
14-
- The amount of code in core is greatly reduced,
15-
- All the kernel code has been moved to the header files (due to this, the problem with LTO optimization is also solved),
16-
- It is possible to set the type of value that will be used in the counter (you can even use several counters with different value types at the same time).
24+
## How to use it:
25+
The library has two API:
26+
1. Complex API for those who want to control everything,
27+
2. Simple API for those who want to quickly add metrics to their C ++ (and it is actually just a wrapper around the complex API).
28+
29+
30+
### Let's start with a simple API because it's simple:
31+
32+
To add it to your C++ project add these lines to your CMakeLists.txt file:
33+
```
34+
add_subdirectory("prometheus-cpp-lite/core")
35+
add_subdirectory("prometheus-cpp-lite/3rdpatry/http-client-lite")
36+
add_subdirectory("prometheus-cpp-lite/simpleapi")
37+
target_link_libraries(your_target prometheus-cpp-simpleapi)
38+
```
39+
40+
The simplest way to create a metric would be like this:
41+
``` c++
42+
prometheus::simpleapi::METRIC_metric_t metric1 { "metric1", "first simple metric without any tag" };
43+
prometheus::simpleapi::METRIC_metric_t metric2 { "metric2", "second simple metric without any tag" };
44+
```
45+
where ```METRIC``` can be ```counter```, ```gauge```, ```summary```, ```histogram``` or ```benchmark```.
46+
47+
If you want to access an existing metric again elsewhere in the code, you can do this:
48+
``` c++
49+
prometheus::simpleapi::METRIC_metric_t metric2_yet_another_link { "metric2", "" };
50+
```
51+
this works because when adding a metric, it checks whether there is already a metric with the same name and, if there is one, a link to it is returned.
52+
53+
You can create a family of metrics (metrics with tags) as follows:
54+
``` c++
55+
prometheus::simpleapi::METRIC_family_t family { "metric_family", "metric family" };
56+
prometheus::simpleapi::METRIC_metric_t metric1 { family.Add({{"name", "metric1"}}) };
57+
prometheus::simpleapi::METRIC_metric_t metric2 { family.Add({{"name", "metric2"}}) };
58+
```
59+
where METRIC can be ```counter```, ```gauge```, ```summary```, ```histogram``` or ```benchmark```.
60+
61+
Next, you can do the following things with metrics:
62+
``` c++
63+
metric++; // for increment it (only for counter and gauge metrics)
64+
metric += value; // for add value to metric (only for gauge metric)
65+
metric -= value; // for sub value from metric (only for gauge metric)
66+
metric = value; // save current value (only gauge metrics)
67+
metric.start(); // start calculate time (only for benchmark metric)
68+
metric.stop(); // stop calculate time (only for benchmark metric)
69+
```
70+
71+
You can change the settings of save (or send) metrics data as follows:
72+
``` c++
73+
prometheus::simpleapi::saver.set_delay(period_in_seconds); // change the period of saving (or sending) metrics data in seconds (5 seconds by default)
74+
prometheus::simpleapi::saver.set_out_file(filename); // change the name of the output file (metrics.prom by default)
75+
prometheus::simpleapi::saver.set_server_url(url); // change the name of prometheus server (unset by default)
76+
```
77+
78+
### Simple API complex example 1 (examples/simpleapi_example.cpp):
79+
80+
``` c++
81+
#include <prometheus/simpleapi.h>
82+
83+
void main() {
84+
85+
using namespace prometheus::simpleapi;
86+
87+
counter_family_t family { "simple_family", "simple family example" };
88+
counter_metric_t metric1 { family.Add({{"name", "counter1"}}) };
89+
counter_metric_t metric2 { family.Add({{"name", "counter2"}}) };
90+
91+
counter_metric_t metric3 { "simple_counter_1", "simple counter 1 without labels example" };
92+
counter_metric_t metric4 { "simple_counter_2", "simple counter 2 without labels example" };
93+
94+
for (;; ) {
95+
std::this_thread::sleep_for(std::chrono::seconds(1));
96+
const int random_value = std::rand();
97+
if (random_value & 1) metric1++;
98+
if (random_value & 2) metric2++;
99+
if (random_value & 4) metric3++;
100+
if (random_value & 8) metric4++;
101+
}
102+
103+
}
104+
```
105+
106+
Output in "metrics.prom" file (by default) will be:
107+
108+
```
109+
# HELP simple_family simple family example
110+
# TYPE simple_family counter
111+
simple_family{name="counter1"} 10
112+
simple_family{name="counter2"} 9
113+
# HELP simple_counter_1 simple counter 1 without labels example
114+
# TYPE simple_counter_1 counter
115+
simple_counter_1 6
116+
# HELP simple_counter_2 simple counter 2 without labels example
117+
# TYPE simple_counter_2 counter
118+
simple_counter_2 8
119+
```
120+
121+
### Simple API complex example 2 (examples/simpleapi_use_in_class_example.cpp):
122+
123+
``` c++
124+
#include <prometheus/simpleapi.h>
125+
126+
using namespace prometheus::simpleapi;
127+
128+
class MyClass {
129+
130+
counter_family_t metric_family { "simple_family", "simple family example" };
131+
counter_metric_t metric1 { metric_family.Add({{"name", "counter1"}}) };
132+
counter_metric_t metric2 { metric_family.Add({{"name", "counter2"}}) };
133+
134+
counter_metric_t metric3 { "simple_counter_1", "simple counter 1 without labels example" };
135+
counter_metric_t metric4 { "simple_counter_2", "simple counter 2 without labels example" };
136+
137+
benchmark_family_t benchmark_family { "simple_benchmark_family", "simple benchmark family example" };
138+
benchmark_metric_t benchmark1 { benchmark_family.Add({{"benchmark", "1"}}) };
139+
benchmark_metric_t benchmark2 { benchmark_family.Add({{"benchmark", "2"}}) };
140+
141+
public:
142+
143+
MyClass() = default;
144+
145+
void member_to_do_something() {
146+
147+
benchmark1.start();
148+
const int random_value = std::rand();
149+
benchmark1.stop();
150+
151+
benchmark2.start();
152+
if (random_value & 1) metric1++;
153+
if (random_value & 2) metric2++;
154+
if (random_value & 4) metric3++;
155+
if (random_value & 8) metric4++;
156+
benchmark2.stop();
157+
158+
}
159+
160+
};
161+
162+
void main() {
163+
164+
MyClass myClass;
165+
benchmark_metric_t benchmark { "simple_benchmark", "simple benchmark example" };
166+
167+
for (;; ) {
168+
169+
benchmark.start();
170+
std::this_thread::sleep_for(std::chrono::seconds(1));
171+
benchmark.stop();
172+
173+
myClass.member_to_do_something();
174+
175+
}
176+
177+
}
178+
```
17179
18-
## What am I going to do next:
19-
- Write a couple of examples how to using the existing core functionality,
20-
- Check and debug this refactored code for Linux mashine (now I worked only in Visual Studio),
21-
- Move from the original project a part of the code responsible for sending metrics through libcurl to the prometheus server, refactoring it and write some examples for it too.
180+
Output in "metrics.prom" file (by default) will be:
22181
182+
```
183+
# HELP simple_family simple family example
184+
# TYPE simple_family counter
185+
simple_family{name="counter1"} 3
186+
simple_family{name="counter2"} 2
187+
# HELP simple_counter_1 simple counter 1 without labels example
188+
# TYPE simple_counter_1 counter
189+
simple_counter_1 3
190+
# HELP simple_counter_2 simple counter 2 without labels example
191+
# TYPE simple_counter_2 counter
192+
simple_counter_2 3
193+
# HELP simple_benchmark_family simple benchmark family example
194+
# TYPE simple_benchmark_family counter
195+
simple_benchmark_family{benchmark="1"} 0.0001088
196+
simple_benchmark_family{benchmark="2"} 1.48e-05
197+
# HELP simple_benchmark simple benchmark example
198+
# TYPE simple_benchmark counter
199+
simple_benchmark 6.0503248
200+
```
23201

0 commit comments

Comments
 (0)