{"id":13611883,"url":"https://github.com/vrischmann/zig-prometheus","last_synced_at":"2025-03-22T15:30:45.483Z","repository":{"id":44141285,"uuid":"391191421","full_name":"vrischmann/zig-prometheus","owner":"vrischmann","description":"Prometheus/VictoriaMetrics client library for Zig","archived":false,"fork":false,"pushed_at":"2025-03-01T20:48:43.000Z","size":79,"stargazers_count":53,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-14T22:54:52.564Z","etag":null,"topics":["prometheus","victoriametrics","zig"],"latest_commit_sha":null,"homepage":"","language":"Zig","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vrischmann.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-07-30T21:29:04.000Z","updated_at":"2025-03-01T20:48:46.000Z","dependencies_parsed_at":"2024-10-28T13:23:12.282Z","dependency_job_id":"6f777f18-a91e-4d07-96ed-8086c64a06a2","html_url":"https://github.com/vrischmann/zig-prometheus","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vrischmann%2Fzig-prometheus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vrischmann%2Fzig-prometheus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vrischmann%2Fzig-prometheus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vrischmann%2Fzig-prometheus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vrischmann","download_url":"https://codeload.github.com/vrischmann/zig-prometheus/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244978413,"owners_count":20541851,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["prometheus","victoriametrics","zig"],"created_at":"2024-08-01T19:02:17.133Z","updated_at":"2025-03-22T15:30:45.181Z","avatar_url":"https://github.com/vrischmann.png","language":"Zig","funding_links":[],"categories":["Zig","Libraries"],"sub_categories":[],"readme":"# zig-prometheus\n\nThis is a [Zig](https://ziglang.org/) library to add [Prometheus](https://prometheus.io/docs/concepts/data_model/)-inspired metrics to a library or application.\n\n\"Inspired\" because it is not strictly compatible with Prometheus, the `Histogram` type is tailored for [VictoriaMetrics](https://github.com/VictoriaMetrics/VictoriaMetrics).\nSee [this blog post](https://valyala.medium.com/improving-histogram-usability-for-prometheus-and-grafana-bc7e5df0e350) from the creator of `VictoriaMetrics` for details.\n\n# Requirements\n\n[Zig master](https://ziglang.org/download/) is the only required dependency.\n\n# Introduction\n\nThis library only provides the following types:\n* A `Registry` holding a number of metrics\n* A `Counter` metric type\n* A `Gauge` metric type\n* A `Histogram` metric type\n\n# Examples\n\nIf you want a quick overview of how to use this library check the [basic example program](examples/basic/main.zig). It showcases everything.\n\n# Reference\n\n## Registry\n\nThe `Registry` is the entry point to obtain a metric type, as well as the type capable of serializing the metrics to a writer.\n\nIn an application it might be useful to have a default, global registry; in a library you probably should take one as a parameter.\n\n### Creation\n\nHere is how to get a registry:\n```zig\nvar registry = try prometheus.Registry(.{}).create(allocator);\ndefer registry.destroy();\n...\n```\n\nYou can also configure some options for the registry:\n```zig\nvar registry = try prometheus.Registry(.{ .max_metrics = 40, .max_name_len = 300 }).create(allocator);\ndefer registry.destroy();\n...\n```\n\nIf you want to store the registry in a variable you probably want to do something like this:\n```zig\nconst Registry = prometheus.Registry(.{ .max_metrics = 40, .max_name_len = 300 });\nvar registry = Registry.create(allocator);\ndefer registry.destroy();\n...\n```\n\nNow you can get metric objects which we will describe later.\n\n### Serializing the metrics\n\nOnce you have a registry you can serialize its metrics to a writer:\n```zig\nvar registry = try prometheus.Registry(.{}).create(allocator);\ndefer registry.destroy();\n\n...\n\nvar file = try std.fs.cwd().createFile(\"metrics.txt\", .{});\ndefer file.close();\n\ntry registry.write(allocator, file.writer());\n```\n\nThe `write` method is thread safe.\n\n## Counter\n\nThe `Counter` type is an atomic integer counter.\n\nHere is an example of how to use a counter:\n\n```zig\nvar registry = try prometheus.Registry(.{}).create(allocator);\ndefer registry.destroy();\n\nvar total_counter = try registry.getOrCreateCounter(\"http_requests_total\");\nvar api_users_counter = try registry.getOrCreateCounter(\n    \\\\http_requests{route=\"/api/v1/users\"}\n);\nvar api_articles_counter = try registry.getOrCreateCounter(\n    \\\\http_requests{route=\"/api/v1/articles\"}\n);\n\ntotal_counter.inc();\ntotal_counter.dec();\ntotal_counter.add(200);\ntotal_counter.set(2400);\nconst counter_value = total_counter.get();\n```\n\nAll methods on a `Counter` are thread safe.\n\n## Gauge\n\nThe `Gauge` type represents a numerical value that is provided by calling a user-supplied function.\n\nA `Gauge` is created with a _state_ and a _function_ which is given that state every time it is called.\n\nFor example, you can imagine a gauge returning the number of connections in a connection pool, the amount of memory allocated, etc.\nBasically anytime the value is instantly queryable it could be a gauge.\n\nOf course, nothing stops you from using a counter to simulate a gauge and calling `set` on it; it's up to you.\n\nHere is an example gauge:\n```zig\nvar registry = try prometheus.Registry(.{}).create(allocator);\ndefer registry.destroy();\n\nconst Conn = struct {};\nconst ConnPool = struct {\n    conns: std.ArrayList(Conn),\n};\nvar pool = ConnPool{ .conns = std.ArrayList.init(allocator) };\n\n_ = try registry.getOrCreateGauge(\n    \"http_conn_pool_size\",\n    \u0026pool,\n    struct {\n        fn get(p: *Pool) f64 {\n            return @intToFloat(f64, p.conns.items.len);\n        }\n    }.get,\n);\n```\n\n## Histogram\n\nThe `Histogram` type samples observations and counts them in automatically created buckets.\n\nIt can be used to observe things like request duration, request size, etc.\n\nHere is a (contrived) example on how to use an histogram:\n```zig\nvar registry = try prometheus.Registry(.{}).create(allocator);\ndefer registry.destroy();\n\nvar request_duration_histogram = try registry.getOrCreateHistogram(\"http_request_duration\");\n\n// Make 100 observations of some expensive operation.\nvar i: usize = 0;\nwhile (i \u003c 100) : (i += 1) {\n    const start = std.time.milliTimestamp();\n\n    var j: usize = 0;\n    var sum: usize = 0;\n    while (j \u003c 2000000) : (j += 1) {\n        sum *= j;\n    }\n\n    request_duration_histogram.update(@intToFloat(f64, std.time.milliTimestamp() - start));\n}\n```\n\n## Using labels\n\nIf you're read the [Prometheus data model](https://prometheus.io/docs/concepts/data_model/#notation), you've seen that a metric can have labels.\n\nOther Prometheus clients provide helpers for this, but not this library: you need to build the proper name yourself.\n\nIf you have static labels then it's easy, just write the label directly like this:\n```zig\nvar http_requests_route_home = try registry.getOrCreateCounter(\n    \\\\http_requests{route=\"/home\"}\n);\nvar http_requests_route_login = try registry.getOrCreateCounter(\n    \\\\http_requests{route=\"/login\"}\n);\nvar http_requests_route_logout = try registry.getOrCreateCounter(\n    \\\\http_requests{route=\"/logout\"}\n);\n...\n```\n\nIf you have dynamic labels you could write a helper function like this:\n```zig\nfn getHTTPRequestsCounter(\n    allocator: *mem.Allocator,\n    registry: *Registry,\n    route: []const u8,\n) !*prometheus.Counter {\n    const name = try std.fmt.allocPrint(allocator, \"http_requests{{route=\\\"{s}\\\"}}\", .{\n        route,\n    });\n    return try registry.getOrCreateCounter(name);\n}\n\nfn handler(route: []const u8) void {\n    var counter = getHTTPRequestsCounter(allocator, registry, route);\n    counter.inc();\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvrischmann%2Fzig-prometheus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvrischmann%2Fzig-prometheus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvrischmann%2Fzig-prometheus/lists"}