1/vrischmann/prometheus v0.7
Prometheus client library
zig-prometheus
This is a Zig library to add Prometheus-inspired metrics to a library or application.
"Inspired" because it is not strictly compatible with Prometheus, the Histogram
type is tailored for VictoriaMetrics.
See this blog post from the creator of VictoriaMetrics
for details.
Requirements
Zig master is the only required dependency.
Introduction
This library only provides the following types:
- A
Registry
holding a number of metrics - A
Counter
metric type - A
Gauge
metric type - A
Histogram
metric type
Examples
If you want a quick overview of how to use this library check the basic example program. It showcases everything.
There's also a more specific example which integrates with the HTTP server Apple Pie. It showcases how to export metrics that are directly scrapable by Prometheus or VictoriaMetrics.
Reference
Registry
The Registry
is the entry point to obtain a metric type, as well as the type capable of serializing the metrics to a writer.
In an application it might be useful to have a default, global registry; in a library you probably should take one as a parameter.
Creation
Here is how to get a registry:
var registry = try prometheus.Registry(.{}).create(allocator);
defer registry.destroy();
...
You can also configure some options for the registry:
var registry = try prometheus.Registry(.{ .max_metrics = 40, .max_name_len = 300 }).create(allocator);
defer registry.destroy();
...
If you want to store the registry in a variable you probably want to do something like this:
const Registry = prometheus.Registry(.{ .max_metrics = 40, .max_name_len = 300 });
var registry = Registry.create(allocator);
defer registry.destroy();
...
Now you can get metric objects which we will describe later.
Serializing the metrics
Once you have a registry you can serialize its metrics to a writer:
var registry = try prometheus.Registry(.{}).create(allocator);
defer registry.destroy();
...
var file = try std.fs.cwd().createFile("metrics.txt", .{});
defer file.close();
try registry.write(allocator, file.writer());
The write
method is thread safe.
Counter
The Counter
type is an atomic integer counter.
Here is an example of how to use a counter:
var registry = try prometheus.Registry(.{}).create(allocator);
defer registry.destroy();
var total_counter = try registry.getOrCreateCounter("http_requests_total");
var api_users_counter = try registry.getOrCreateCounter(
\\http_requests{route="/api/v1/users"}
);
var api_articles_counter = try registry.getOrCreateCounter(
\\http_requests{route="/api/v1/articles"}
);
total_counter.inc();
total_counter.dec();
total_counter.add(200);
total_counter.set(2400);
const counter_value = total_counter.get();
All methods on a Counter
are thread safe.
Gauge
The Gauge
type represents a numerical value that is provided by calling a user-supplied function.
A Gauge
is created with a state and a function which is given that state every time it is called.
For example, you can imagine a gauge returning the number of connections in a connection pool, the amount of memory allocated, etc. Basically anytime the value is instantly queryable it could be a gauge.
Of course, nothing stops you from using a counter to simulate a gauge and calling set
on it; it's up to you.
Here is an example gauge:
var registry = try prometheus.Registry(.{}).create(allocator);
defer registry.destroy();
const Conn = struct {};
const ConnPool = struct {
conns: std.ArrayList(Conn),
};
var pool = ConnPool{ .conns = std.ArrayList.init(allocator) };
_ = try registry.getOrCreateGauge(
"http_conn_pool_size",
&pool,
struct {
fn get(p: *Pool) f64 {
return @intToFloat(f64, p.conns.items.len);
}
}.get,
);
Histogram
The Histogram
type samples observations and counts them in automatically created buckets.
It can be used to observe things like request duration, request size, etc.
Here is a (contrived) example on how to use an histogram:
var registry = try prometheus.Registry(.{}).create(allocator);
defer registry.destroy();
var request_duration_histogram = try registry.getOrCreateHistogram("http_request_duration");
// Make 100 observations of some expensive operation.
var i: usize = 0;
while (i < 100) : (i += 1) {
const start = std.time.milliTimestamp();
var j: usize = 0;
var sum: usize = 0;
while (j < 2000000) : (j += 1) {
sum *= j;
}
request_duration_histogram.update(@intToFloat(f64, std.time.milliTimestamp() - start));
}
Using labels
If you're read the Prometheus data model, you've seen that a metric can have labels.
Other Prometheus clients provide helpers for this, but not this library: you need to build the proper name yourself.
If you have static labels then it's easy, just write the label directly like this:
var http_requests_route_home = try registry.getOrCreateCounter(
\\http_requests{route="/home"}
);
var http_requests_route_login = try registry.getOrCreateCounter(
\\http_requests{route="/login"}
);
var http_requests_route_logout = try registry.getOrCreateCounter(
\\http_requests{route="/logout"}
);
...
If you have dynamic labels you could write a helper function like this:
fn getHTTPRequestsCounter(
allocator: *mem.Allocator,
registry: *Registry,
route: []const u8,
) !*prometheus.Counter {
const name = try std.fmt.allocPrint(allocator, "http_requests{{route=\"{s}\"}}", .{
route,
});
return try registry.getOrCreateCounter(name);
}
fn handler(route: []const u8) void {
var counter = getHTTPRequestsCounter(allocator, registry, route);
counter.inc();
}
Package Contents
- .gitattributes
- zigmod.lock
- LICENSE
- .github/workflows/main.yml
- examples/basic/main.zig
- examples/apple_pie/main.zig
- build.zig
- src/Histogram.zig
- src/Counter.zig
- src/Gauge.zig
- src/main.zig
- src/metric.zig
- README.md
- zig.mod
- .gitignore
Root Dependencies
-
git https://github.com/Luukdegram/apple_pie branch-master
Build Dependencies
-
git https://github.com/Luukdegram/apple_pie branch-master
History
Published On | Tree @ Commit | Size | |
---|---|---|---|
v0.28 | Wed, 21 Feb 2024 08:12:46 UTC | Tree | 46.151 KB |
v0.27 | Wed, 21 Feb 2024 08:10:41 UTC | Tree | 46.214 KB |
v0.26 | Sun, 26 Nov 2023 16:17:45 UTC | Tree | 46.149 KB |
v0.25 | Thu, 23 Nov 2023 19:51:31 UTC | Tree | 48.491 KB |
v0.24 | Thu, 23 Nov 2023 19:48:11 UTC | Tree | 48.401 KB |
v0.23 | Thu, 23 Nov 2023 19:45:10 UTC | Tree | 48.389 KB |
v0.22 | Tue, 07 Nov 2023 10:35:32 UTC | Tree | 48.377 KB |
v0.21 | Thu, 21 Sep 2023 11:07:28 UTC | Tree | 48.377 KB |
v0.20 | Mon, 07 Aug 2023 20:19:05 UTC | Tree | 48.317 KB |
v0.19 | Sun, 02 Jul 2023 13:25:20 UTC | Tree | 48.238 KB |
v0.18 | Sun, 02 Jul 2023 13:15:40 UTC | Tree | 48.243 KB |
v0.17 | Thu, 22 Jun 2023 20:38:56 UTC | Tree | 48.258 KB |
v0.16 | Tue, 20 Jun 2023 22:53:01 UTC | Tree | 48.254 KB |
v0.15 | Sun, 11 Jun 2023 10:34:31 UTC | Tree | 48.232 KB |
v0.14 | Wed, 31 May 2023 21:03:13 UTC | Tree | 48.226 KB |
v0.13 | Wed, 31 May 2023 20:40:23 UTC | Tree | 47.211 KB |
v0.12 | Wed, 31 May 2023 20:30:44 UTC | Tree | 46.848 KB |
v0.11 | Wed, 31 May 2023 08:51:46 UTC | Tree | 46.078 KB |
v0.10 | Mon, 29 May 2023 20:46:27 UTC | Tree | 46.079 KB |
v0.9 | Tue, 16 May 2023 18:43:49 UTC | Tree | 44.860 KB |
v0.8 | Tue, 02 May 2023 17:47:47 UTC | Tree | 44.779 KB |
v0.7 | Mon, 12 Dec 2022 20:01:30 UTC | Tree | 44.793 KB |
v0.6 | Sat, 08 Oct 2022 17:45:12 UTC | Tree | 44.786 KB |
v0.5 | Sun, 31 Jul 2022 16:52:52 UTC | Tree | 44.786 KB |
v0.4 | Tue, 26 Jul 2022 18:40:33 UTC | Tree | 45.276 KB |
v0.3 | Tue, 31 May 2022 21:27:52 UTC | Tree | 45.279 KB |
v0.2 | Fri, 11 Feb 2022 22:22:48 UTC | Tree | 45.279 KB |
v0.1 | Sat, 05 Feb 2022 00:17:50 UTC | Tree | 44.682 KB |