{"id":13463819,"url":"https://github.com/knyar/nginx-lua-prometheus","last_synced_at":"2025-05-14T11:09:39.686Z","repository":{"id":37926631,"uuid":"54273831","full_name":"knyar/nginx-lua-prometheus","owner":"knyar","description":"Prometheus metric library for Nginx written in Lua","archived":false,"fork":false,"pushed_at":"2025-01-04T08:43:30.000Z","size":174,"stargazers_count":1496,"open_issues_count":5,"forks_count":232,"subscribers_count":25,"default_branch":"main","last_synced_at":"2025-04-11T21:48:55.380Z","etag":null,"topics":["lua","metrics","monitoring","nginx","prometheus"],"latest_commit_sha":null,"homepage":"","language":"Lua","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/knyar.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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,"zenodo":null}},"created_at":"2016-03-19T15:51:04.000Z","updated_at":"2025-04-11T04:56:23.000Z","dependencies_parsed_at":"2024-05-30T08:04:44.340Z","dependency_job_id":"6a34c171-ed4e-4e68-abee-7682ad7ac7fa","html_url":"https://github.com/knyar/nginx-lua-prometheus","commit_stats":{"total_commits":126,"total_committers":25,"mean_commits":5.04,"dds":0.5079365079365079,"last_synced_commit":"988be4d4ef9fb68f25b897a22d554e0d98207f94"},"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/knyar%2Fnginx-lua-prometheus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/knyar%2Fnginx-lua-prometheus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/knyar%2Fnginx-lua-prometheus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/knyar%2Fnginx-lua-prometheus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/knyar","download_url":"https://codeload.github.com/knyar/nginx-lua-prometheus/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254129489,"owners_count":22019628,"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":["lua","metrics","monitoring","nginx","prometheus"],"created_at":"2024-07-31T14:00:28.947Z","updated_at":"2025-05-14T11:09:39.644Z","avatar_url":"https://github.com/knyar.png","language":"Lua","readme":"[![Coverage Status](https://coveralls.io/repos/github/knyar/nginx-lua-prometheus/badge.svg?branch=master)](https://coveralls.io/github/knyar/nginx-lua-prometheus?branch=master)\n\n# Prometheus metric library for Nginx\n\nThis is a Lua library that can be used with Nginx to keep track of metrics and\nexpose them on a separate web page to be pulled by\n[Prometheus](https://prometheus.io).\n\n## Installation\n\nTo use this library, you will need the [ngx_lua](\nhttps://github.com/openresty/lua-nginx-module) nginx module. You can either use\na lua-enabled nginx-based server like [OpenResty](https://openresty.org/en/),\nor a regular nginx server with the module enabled: for example, on Debian 10 you\ncan simply install `libnginx-mod-http-lua` (but please read the [known issues](\n#known-issues) if you use a later Debian version).\n\nThe library file - `prometheus.lua` - needs to be available in `LUA_PATH`. If\nthis is the only Lua library you use, you can just point `lua_package_path` to\nthe directory with this git repo checked out (see example below).\n\nOpenResty users will find this library in [opm](https://opm.openresty.org/package/knyar/nginx-lua-prometheus/). It\nis also available via\n[luarocks](https://luarocks.org/modules/knyar/nginx-lua-prometheus).\n\n## Quick start guide\n\nTo track request latency broken down by server name and request count\nbroken down by server name and status, add the following to the `http` section\nof `nginx.conf`:\n\n```nginx\nlua_shared_dict prometheus_metrics 10M;\nlua_package_path \"/path/to/nginx-lua-prometheus/?.lua;;\";\n\ninit_worker_by_lua_block {\n  prometheus = require(\"prometheus\").init(\"prometheus_metrics\")\n\n  metric_requests = prometheus:counter(\n    \"nginx_http_requests_total\", \"Number of HTTP requests\", {\"host\", \"status\"})\n  metric_latency = prometheus:histogram(\n    \"nginx_http_request_duration_seconds\", \"HTTP request latency\", {\"host\"})\n  metric_connections = prometheus:gauge(\n    \"nginx_http_connections\", \"Number of HTTP connections\", {\"state\"})\n}\n\nlog_by_lua_block {\n  metric_requests:inc(1, {ngx.var.server_name, ngx.var.status})\n  metric_latency:observe(tonumber(ngx.var.request_time), {ngx.var.server_name})\n}\n```\n\nThis:\n* configures a shared dictionary for your metrics called `prometheus_metrics`\n  with a 10MB size limit;\n* registers a counter called `nginx_http_requests_total` with two labels:\n  `host` and `status`;\n* registers a histogram called `nginx_http_request_duration_seconds` with one\n  label `host`;\n* registers a gauge called `nginx_http_connections` with one label `state`;\n* on each HTTP request measures its latency, recording it in the histogram and\n  increments the counter, setting current server name as the `host` label and\n  HTTP status code as the `status` label.\n\nLast step is to configure a separate server that will expose the metrics.\nPlease make sure to only make it reachable from your Prometheus server:\n\n```nginx\nserver {\n  listen 9145;\n  allow 192.168.0.0/16;\n  deny all;\n  location /metrics {\n    content_by_lua_block {\n      metric_connections:set(ngx.var.connections_reading, {\"reading\"})\n      metric_connections:set(ngx.var.connections_waiting, {\"waiting\"})\n      metric_connections:set(ngx.var.connections_writing, {\"writing\"})\n      prometheus:collect()\n    }\n  }\n}\n```\n\nMetrics will be available at `http://your.nginx:9145/metrics`. Note that the\ngauge metric in this example contains values obtained from nginx global state,\nso they get set immediately before metrics are returned to the client.\n\n## API reference\n\n### init()\n\n**syntax:** require(\"prometheus\").init(*dict_name*, [*options*]])\n\nInitializes the module. This should be called once from the\n[init_worker_by_lua_block](https://github.com/openresty/lua-nginx-module#init_worker_by_lua_block)\nsection of nginx configuration.\n\n* `dict_name` is the name of the nginx shared dictionary which will be used to\n  store all metrics. Defaults to `prometheus_metrics` if not specified.\n* `options` is a table of configuration options that can be provided. Accepted\n  options are:\n  * `prefix` (string): metric name prefix. This string will be prepended to\n    metric names on output.\n  * `error_metric_name` (string): Can be used to change the default name of\n    error metric (see [Built-in metrics](#built-in-metrics) for details).\n  * `sync_interval` (number): sets the sync interval for per-worker counters and\n    key index (in seconds). This sets the boundary on eventual consistency of\n    counter metric increments, and metric resets/deletions. Defaults to 1.\n\nReturns a `prometheus` object that should be used to register metrics.\n\nExample:\n```nginx\ninit_worker_by_lua_block {\n  prometheus = require(\"prometheus\").init(\"prometheus_metrics\", {sync_interval=3})\n}\n```\n\n### prometheus:counter()\n\n**syntax:** prometheus:counter(*name*, *description*, *label_names*)\n\nRegisters a counter. Should be called once for each counter from the\n[init_worker_by_lua_block](\nhttps://github.com/openresty/lua-nginx-module#init_worker_by_lua_block)\nsection.\n\n* `name` is the name of the metric.\n* `description` is the text description that will be presented to Prometheus\n  along with the metric. Optional (pass `nil` if you still need to define\n  label names).\n* `label_names` is an array of label names for the metric. Optional.\n\n[Naming section](https://prometheus.io/docs/practices/naming/) of Prometheus\ndocumentation provides good guidelines on choosing metric and label names.\n\nReturns a `counter` object that can later be incremented.\n\nExample:\n```nginx\ninit_worker_by_lua_block {\n  prometheus = require(\"prometheus\").init(\"prometheus_metrics\")\n\n  metric_bytes = prometheus:counter(\n    \"nginx_http_request_size_bytes\", \"Total size of incoming requests\")\n  metric_requests = prometheus:counter(\n    \"nginx_http_requests_total\", \"Number of HTTP requests\", {\"host\", \"status\"})\n}\n```\n\n### prometheus:gauge()\n\n**syntax:** prometheus:gauge(*name*, *description*, *label_names*)\n\nRegisters a gauge. Should be called once for each gauge from the\n[init_worker_by_lua_block](\nhttps://github.com/openresty/lua-nginx-module#init_worker_by_lua_block)\nsection.\n\n* `name` is the name of the metric.\n* `description` is the text description that will be presented to Prometheus\n  along with the metric. Optional (pass `nil` if you still need to define\n  label names).\n* `label_names` is an array of label names for the metric. Optional.\n\nReturns a `gauge` object that can later be set.\n\nExample:\n```nginx\ninit_worker_by_lua_block {\n  prometheus = require(\"prometheus\").init(\"prometheus_metrics\")\n\n  metric_connections = prometheus:gauge(\n    \"nginx_http_connections\", \"Number of HTTP connections\", {\"state\"})\n}\n```\n\n### prometheus:histogram()\n\n**syntax:** prometheus:histogram(*name*, *description*, *label_names*,\n  *buckets*)\n\nRegisters a histogram. Should be called once for each histogram from the\n[init_worker_by_lua_block](\nhttps://github.com/openresty/lua-nginx-module#init_worker_by_lua_block)\nsection.\n\n* `name` is the name of the metric.\n* `description` is the text description. Optional.\n* `label_names` is an array of label names for the metric. Optional.\n* `buckets` is an array of numbers defining bucket boundaries. Optional,\n  defaults to 20 latency buckets covering a range from 5ms to 10s (in seconds).\n\nReturns a `histogram` object that can later be used to record samples.\n\nExample:\n```nginx\ninit_worker_by_lua_block {\n  prometheus = require(\"prometheus\").init(\"prometheus_metrics\")\n\n  metric_latency = prometheus:histogram(\n    \"nginx_http_request_duration_seconds\", \"HTTP request latency\", {\"host\"})\n  metric_response_sizes = prometheus:histogram(\n    \"nginx_http_response_size_bytes\", \"Size of HTTP responses\", nil,\n    {10,100,1000,10000,100000,1000000})\n}\n```\n\n### prometheus:collect()\n\n**syntax:** prometheus:collect()\n\nPresents all metrics in a text format compatible with Prometheus. This should be\ncalled in\n[content_by_lua_block](https://github.com/openresty/lua-nginx-module#content_by_lua_block)\nto expose the metrics on a separate HTTP page.\n\nExample:\n```nginx\nlocation /metrics {\n  content_by_lua_block { prometheus:collect() }\n  allow 192.168.0.0/16;\n  deny all;\n}\n```\n\n### prometheus:metric_data()\n\n**syntax:** prometheus:metric_data()\n\nReturns metric data as an array of strings.\n\n### counter:inc()\n\n**syntax:** counter:inc(*value*, *label_values*)\n\nIncrements a previously registered counter. This is usually called from\n[log_by_lua_block](https://github.com/openresty/lua-nginx-module#log_by_lua_block)\nglobally or per server/location.\n\n* `value` is a value that should be added to the counter. Defaults to 1.\n* `label_values` is an array of label values.\n\nThe number of label values should match the number of label names defined when\nthe counter was registered using `prometheus:counter()`. No label values should\nbe provided for counters with no labels. Non-printable characters will be\nstripped from label values.\n\nExample:\n```nginx\nlog_by_lua_block {\n  metric_bytes:inc(tonumber(ngx.var.request_length))\n  metric_requests:inc(1, {ngx.var.server_name, ngx.var.status})\n}\n```\n\n### counter:del()\n\n**syntax:** counter:del(*label_values*)\n\nDelete a previously registered counter. This is usually called when you don't\nneed to observe such counter (or a metric with specific label values in this\ncounter) any more. If this counter has labels, you have to pass `label_values`\nto delete the specific metric of this counter. If you want to delete all the\nmetrics of a counter with labels, you should call `Counter:reset()`.\n\n* `label_values` is an array of label values.\n\nThe number of label values should match the number of label names defined when\nthe counter was registered using `prometheus:counter()`. No label values should\nbe provided for counters with no labels. Non-printable characters will be\nstripped from label values.\n\nThis function will wait for `sync_interval` before deleting the metric to\nallow all workers to sync their counters.\n\n### counter:reset()\n\n**syntax:** counter:reset()\n\nDelete all metrics for a previously registered counter. If this counter have no\nlabels, it is just the same as `Counter:del()` function. If this counter have labels,\nit will delete all the metrics with different label values.\n\nThis function will wait for `sync_interval` before deleting the metrics to\nallow all workers to sync their counters.\n\n### gauge:set()\n\n**syntax:** gauge:set(*value*, *label_values*)\n\nSets the current value of a previously registered gauge. This could be called\nfrom [log_by_lua_block](https://github.com/openresty/lua-nginx-module#log_by_lua_block)\nglobally or per server/location to modify a gauge on each request, or from\n[content_by_lua_block](https://github.com/openresty/lua-nginx-module#content_by_lua_block)\njust before `prometheus::collect()` to return a real-time value.\n\n* `value` is a value that the gauge should be set to. Required.\n* `label_values` is an array of label values.\n\n### gauge:inc()\n\n**syntax:** gauge:inc(*value*, *label_values*)\n\nIncrements or decrements a previously registered gauge. This is usually called\nwhen you want to observe the real-time value of a metric that can both be\nincreased and decreased.\n\n* `value` is a value that should be added to the gauge. It could be a negative\nvalue when you need to decrease the value of the gauge. Defaults to 1.\n* `label_values` is an array of label values.\n\nThe number of label values should match the number of label names defined when\nthe gauge was registered using `prometheus:gauge()`. No label values should\nbe provided for gauges with no labels. Non-printable characters will be\nstripped from label values.\n\n### gauge:del()\n\n**syntax:** gauge:del(*label_values*)\n\nDelete a previously registered gauge. This is usually called when you don't\nneed to observe such gauge (or a metric with specific label values in this\ngauge) any more. If this gauge has labels, you have to pass `label_values`\nto delete the specific metric of this gauge. If you want to delete all the\nmetrics of a gauge with labels, you should call `Gauge:reset()`.\n\n* `label_values` is an array of label values.\n\nThe number of label values should match the number of label names defined when\nthe gauge was registered using `prometheus:gauge()`. No label values should\nbe provided for gauges with no labels. Non-printable characters will be\nstripped from label values.\n\n### gauge:reset()\n\n**syntax:** gauge:reset()\n\nDelete all metrics for a previously registered gauge. If this gauge have no\nlabels, it is just the same as `Gauge:del()` function. If this gauge have labels,\nit will delete all the metrics with different label values.\n\n### histogram:observe()\n\n**syntax:** histogram:observe(*value*, *label_values*)\n\nRecords a value in a previously registered histogram. Usually called from\n[log_by_lua_block](https://github.com/openresty/lua-nginx-module#log_by_lua_block)\nglobally or per server/location.\n\nNote that recording an observation requires incrementing several histogram\ncounters, which does not happen atomically and might race with metric\ncollection (see #161).\n\n* `value` is a value that should be recorded. Required.\n* `label_values` is an array of label values.\n\nExample:\n```nginx\nlog_by_lua_block {\n  metric_latency:observe(tonumber(ngx.var.request_time), {ngx.var.server_name})\n  metric_response_sizes:observe(tonumber(ngx.var.bytes_sent))\n}\n```\n\n### histogram:reset()\n\n**syntax:** histogram:reset()\n\nDelete all metrics for a previously registered histogram.\n\nThis function will wait for `sync_interval` before deleting the metrics to\nallow all workers to sync their counters.\n\n### Built-in metrics\n\nThe module increments an error metric called `nginx_metric_errors_total`\n(unless another name was configured in [init()](#init)) if it encounters\nan error (for example, when `lua_shared_dict` becomes full). You might want\nto configure an alert on that metric.\n\n## Caveats\n\n### Usage in stream module\n\nFor now, there is no way to share a dictionary between HTTP and Stream modules\nin Nginx. If you are using this library to collect metrics from stream module,\nyou will need to configure a separate endpoint to return them. Here's an\nexample.\n\n```nginx\nserver {\n  listen 9145;\n  content_by_lua_block {\n    local sock = assert(ngx.req.socket(true))\n    local data = sock:receive()\n    local location = \"GET /metrics\"\n    if string.sub(data, 1, string.len(location)) == location then\n      ngx.say(\"HTTP/1.1 200 OK\")\n      ngx.say(\"Content-Type: text/plain\")\n      ngx.say(\"\")\n      ngx.say(table.concat(prometheus:metric_data(), \"\"))\n    else\n      ngx.say(\"HTTP/1.1 404 Not Found\")\n    end\n  }\n}\n```\n\n## Known issues\n\n### libnginx-mod-http-lua broken in some Debian and Ubuntu versions\n\nNote that recent stable versions of Debian and Ubuntu are known to package\n`ngx_lua` version incompatible with the version of `nginx` shipped in the same\ndistro. This results in nginx process segfaulting when the lua module is used,\nmaking it completely unusable. In such case nginx error logs will clearly\nindicate that the process crashed, e.g.:\n\n```\n[alert] 123#123: worker process 45678 exited on signal 11\n```\n\nThe following versions of Debian and Ubuntu have been known to have this\nissue:\n\n* Debian 11 (bug [#994178](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=994178))\n* Ubuntu 20.04 and 21.04 (bug [#1893753](https://bugs.launchpad.net/ubuntu/+source/nginx/+bug/1893753))\n\n### ngx.sleep(0) called without delayed events patch\n\nYou might see the following warning logged by nginx when metrics are being\ncollected:\n\n\u003e [warn] ngx.sleep(0) called without delayed events patch, this will hurt performance\n\nThis is a side effect of a performance optimization added for OpenResty. While\ngenerating metric data, the library aims to occasionally yield control back to\nthe nginx event loop to avoid blocking the worker process and causing increased\nlatency for other in-flight requests.\n\nThis warning is displayed when the library is used with nginx that lacks\nOpenResty patches and can be ignored.\n\n## Troubleshooting\n\n### Make sure that nginx lua module is enabled\n\nIf you experience problems indicating that nginx doesn't know how to interpret\nlua scripts, please make sure that [the lua\nmodule](https://github.com/openresty/lua-nginx-module) is enabled. You might\nneed something like this in your `nginx.conf`:\n\n```nginx\nload_module modules/ndk_http_module.so;\nload_module modules/ngx_http_lua_module.so;\n```\n\n### Keep lua code cache enabled\n\nThis module expects the\n[lua_code_cache](https://github.com/openresty/lua-nginx-module#lua_code_cache)\noption to be `on` (which is the default).\n\n### Try using an older version of the library\n\nIf you are seeing library initialization errors, followed by errors for each\nmetric change request (e.g. *attempt to index global '...' (a nil value)*),\nyou are probably using an old version of lua-nginx-module. For example, this\nwill happen if you try using the latest version of this library with the\n`nginx-extras` package shipped with Ubuntu 16.04.\n\nIf you cannot upgrade nginx and lua-nginx-module, you can try using an older\nversion of this library; it will not have the latest performance optimizations,\nbut will still be functional. The recommended older release to use is\n[0.20181120](https://github.com/knyar/nginx-lua-prometheus/tree/0.20181120).\n\n## Development\n\n### Install dependencies for testing\n\n- `luarocks install luacheck`\n- `luarocks install luaunit`\n\n### Run tests\n\n- `luacheck --globals ngx -- prometheus.lua`\n- `lua prometheus_test.lua`\n- `cd integration \u0026\u0026 ./test.sh` (requires Docker and Go)\n\n### Releasing new version\n\n- update CHANGELOG.md\n- update version in the `dist.ini`\n- rename `.rockspec` file and update version inside it\n- commit changes\n- create a new Git tag: `git tag 0.XXXXXXXX \u0026\u0026 git push origin 0.XXXXXXXX`\n- push to luarocks: `luarocks upload nginx-lua-prometheus-0.20181120-1.rockspec`\n- upload to OPM: `opm build \u0026\u0026 opm upload`\n\n## Credits\n\n- Created and maintained by Anton Tolchanov ([@knyar](https://github.com/knyar))\n- Metrix prefix support contributed by david birdsong ([@davidbirdsong](\n  https://github.com/davidbirdsong))\n- Gauge support contributed by Cosmo Petrich ([@cosmopetrich](\n  https://github.com/cosmopetrich))\n- Performance improvements and per-worker counters are contributed by Wangchong\n  Zhou ([@fffonion](https://github.com/fffonion)) / [@Kong](\n  https://github.com/Kong).\n- Metric name tracking improvements contributed by Jan Dolinár ([@dolik-rce](\n  https://github.com/dolik-rce))\n\n## License\n\nLicensed under MIT license.\n\n### Third Party License\n\nFollowing third party modules are used in this library:\n\n- [Kong/lua-resty-counter](https://github.com/Kong/lua-resty-counter)\n\nThis module is licensed under the Apache 2.0 license.\n\nCopyright (C) 2019, Kong Inc.\n\nAll rights reserved.\n\n","funding_links":[],"categories":["Performance","Lua","Resources"],"sub_categories":["Web Plataforms"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fknyar%2Fnginx-lua-prometheus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fknyar%2Fnginx-lua-prometheus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fknyar%2Fnginx-lua-prometheus/lists"}