lua-resty-p8s
New string.buffer prometheus metrics module for the ngx_lua module
$ opm get bjne/lua-resty-p8s
prometheus (p8s) metric library for nginx/openresty
This is a Lua library that can be used with Nginx to keep track of metrics and expose them on a separate web page to be pulled by Prometheus.
Installation
copy the contents of the lib directory recursively to a path available in lua_package_path
openresty users will find this library in opm.
Quick start guide
To track request latency broken down by server name and request count broken down by server name and status, add the following to the http
section of nginx.conf
:
lua_shared_dict resty_p8s 10M;
lua_package_path "/path/to/lua-resty-p8s/lib/?.lua;;";
init_by_lua_block {
_G.p8s = require "resty.p8s"
}
init_worker_by_lua_block {
-- set con to nomerge as its generated on request
_G.con = p8s.gauge("con", "state"):help("http connections"):merge(false)
_G.req = p8s.counter("req", "host", "status"):help("http requests")
_G.lat = p8s.histogram("lat", "host"):help("request latency")
}
log_by_lua_block {
req(1, ngx.var.server_name, ngx.var.status)
lat(ngx.var.request_time, ngx.var.server_name)
}
server {
location /enable_internal_metrics {
-- enables internal metrics for a spesific worker (or true for all)
content_by_lua_block {
p8s.enable_internal_metrics(true)
}
}
location /disable_internal_metrics {
-- disables internal metrics for a spesific worker (or true for all)
content_by_lua_block {
p8s.disable_internal_metrics(true)
}
}
location /no_internal_metrics {
content_by_lua_block {
p8s(false)
}
}
location /reset_internal_metrics_for_all_workers {
content_by_lua_block {
p8s.reset_internal_metrics(true)
}
}
location /ordered_output_with_internal_metrics {
content_by_lua_block { p8s(true, true) }
}
}
configures a shared dictionary with the default name
resty_p8s
registers a gauge called
con
with one labelstate
registers a counter called
req
with two labels:host
andstatus
registers a histogram called
lat
with one labelhost
on each HTTP request measures its latency, recording it in the histogram and increments the counter, setting current server name as the
host
label and HTTP status code as thestatus
label.
Last step is to configure a separate server that will expose the metrics.
server {
listen 9145;
allow 10.0.0.0/8;
deny all;
location /metrics {
content_by_lua_block {
con(ngx.var.connections_reading, "reading")
con(ngx.var.connections_waiting, "waiting")
con(ngx.var.connections_writing, "writing")
p8s()
}
}
}
Metrics will be available at http://your.nginx:9145/metrics
. Note that the gauge metric in this example contains values obtained from nginx global state, so they get set immediately before metrics are returned to the client.
API reference
init()
syntax: require("p8s").init(sync_interval or dict_name, sync_interval or dict_name)
Initializes the module. This should be called once from init
and/or init_worker
If called from init
sync-timers are not started, but will be autostarted first time a metric is created in any other phase (or .init is called again without argument needed in init_worker)
dict_name
is the name of the nginx shared dictionary which will be used to store all metrics. Defaults tolua_resty_p8s
if not specified. if can also be specified as a reference to a shared dictsync_interval
): sets per-worker counter sync interval in seconds, default 1
Returns a p8s
object that should be used to register metrics.
Example:
init_worker_by_lua_block {
p8s = require("p8s").init("i_want_to_use_my_own_dict_name_for_some_reason")
}
p8s.counter()
syntax: p8s.counter(name, label_name, ...)
name
is the name of the metric.label_name
list of label names. Optional.
Naming section of Prometheus documentation provides good guidelines on choosing metric and label names.
Returns a counter
object that can later be incremented.
Example:
init_worker_by_lua_block {
p8s = require("p8s").init()
metric_bytes = p8s.counter("nginx_http_request_size_bytes")
metric_requests = p8s.counter("nginx_http_requests_total", "host", "status")
}
p8s.gauge()
syntax: p8s.gauge(name, label_name, ...)
name
is the name of the metric.label_name
list of label names. Optional.
Returns a gauge
object that can later be set.
Example:
init_worker_by_lua_block {
p8s = require("p8s").init()
metric_connections = p8s.gauge("nginx_http_connections", "state")
}
p8s.histogram()
syntax: p8s.histogram(name, buckets, label_name, ...)
name
is the name of the metric.buckets
is an array of numbers defining bucket boundaries. Optional, defaults to 20 latency buckets covering a range from 5ms to 10s (in seconds).label_name
list of label names. Optional
Returns a histogram
object that can later be used to record samples.
Example:
init_worker_by_lua_block {
p8s = require("p8s").init()
metric_latency = p8s.histogram("nginx_http_request_duration_seconds", "host"}
metric_response_sizes = p8s.histogram(
"nginx_http_response_size_bytes", {10,100,1000,10000,100000,1000000}
)
}
p8s()
syntax: p8s()
Presents all metrics in a text format compatible with Prometheus. This should be called in content_by_lua_block to expose the metrics on a separate HTTP page.
Example:
location /metrics {
content_by_lua_block { p8s() }
}
counter:incr() or counter()
syntax: counter:incr(value, label_value, ...)
Increments a previously registered counter.
value
is a value that should be added to the counter. Defaults to 1label_value
zero or more label values
The number of label values should match the number of label names defined when the counter was registered using p8s.counter()
. No label values should be provided for counters with no labels.
Example:
log_by_lua_block {
metric_bytes(ngx.var.request_length)
metric_requests(1, ngx.var.server_name, ngx.var.status)
}
gauge:set() or gauge()
syntax: gauge:set(value, label_value, ...)
Sets the current value of a previously registered gauge.
value
is a value that the gauge should be set to. Required.label_value
zero or more label values
histogram:observe() or histogram()
syntax: histogram:observe(value, label_value, ...)
Records a value in a previously registered histogram.
value
is a value that should be recorded. Required.label_value
zero or more label values
Example:
log_by_lua_block {
metric_latency(ngx.var.request_time, ngx.var.server_name)
metric_response_sizes(ngx.var.bytes_sent)
}
(gauge or counter or histogram):reset(worker)
syntax: (gauge or counter or histogram):reset(worker)
Resets a metric to zero for current worker by default
worker
can be null for current worker, a id ortrue
for all workers
reset
returns self, so it can be nested like
Example:
gauge:reset():set(10, "foo")
(gauge or counter or histogram):help(help)
syntax: (gauge or counter or histogram):help(help)
Sets a HELP text for current metric, if that is something you want to waste bytes on
help
text, nil to clear current help
(gauge or counter or histogram):labels(*label,...)
syntax: (gauge or counter or histogram):labels(label, ...)
Sets default labels for a metric
Example:
local counter = p8s.counter("counter", "worker", "event"):labels(ngx.worker.id())
counter(1, "some event")
local counter2 = p8s.counter("counter", "something", "event"):labels(nil, "some event")
counter(1, "something")
Testing
cpan Test::Nginx Test::Nginx::Socket
./test.sh
What is different compared to alternatives
This module uses LuaJIT serialization instead of pure shm to synchronize metrics between workers. This means all counter updates are only done in the local lua VM, and cross worker updates are a single shm write/interval
Rendering of prometheus output format is nworkers shm gets, and a local merge. This should perform well when using multiple counters
Metrics are garbagecollected, so no need to delete them, just let the lua gc take care of it. Keep in mind tho, that you need to keep a reference.
On reload (currenly) data is loaded from shm, but unless the same metric if created again, garbagecollection may currently remove the data before its recreated. Creating metrics in init_worker
will mitigate this issue
Authors
Bjørnar Ness
License
2bsd
Dependencies
luajit
Versions
-
bjne/lua-resty-p8s 0.3.1New string.buffer prometheus metrics module for the ngx_lua module 2023-12-18 21:06:25
-
bjne/lua-resty-p8s 0.3.0New string.buffer prometheus metrics module for the ngx_lua module 2023-12-18 17:56:32
-
bjne/lua-resty-p8s 0.2.7New string.buffer prometheus metrics module for the ngx_lua module 2023-12-18 17:28:02
-
bjne/lua-resty-p8s 0.2.6New string.buffer prometheus metrics module for the ngx_lua module 2023-12-18 12:29:03
-
bjne/lua-resty-p8s 0.2.5New string.buffer prometheus metrics module for the ngx_lua module 2023-12-17 22:05:39
-
bjne/lua-resty-p8s 0.2.4New string.buffer prometheus metrics module for the ngx_lua module 2023-12-17 20:52:56
-
bjne/lua-resty-p8s 0.2.3New string.buffer prometheus metrics module for the ngx_lua module 2023-12-17 20:51:10
-
bjne/lua-resty-p8s 0.2.2New string.buffer prometheus metrics module for the ngx_lua module 2023-12-16 22:35:01
-
bjne/lua-resty-p8s 0.2.1New string.buffer prometheus metrics module for the ngx_lua module 2023-12-16 16:31:58
-
bjne/lua-resty-p8s 0.2.0New string.buffer prometheus metrics module for the ngx_lua module 2023-12-16 16:11:11
-
bjne/lua-resty-p8s 0.1.11New string.buffer prometheus metrics module for the ngx_lua module 2023-12-16 15:44:53
-
bjne/lua-resty-p8s 0.1.10New string.buffer prometheus metrics module for the ngx_lua module 2023-12-16 12:51:01
-
bjne/lua-resty-p8s 0.1.9New string.buffer prometheus metrics module for the ngx_lua module 2023-12-16 12:45:43
-
bjne/lua-resty-p8s 0.1.8New string.buffer prometheus metrics module for the ngx_lua module 2023-12-16 12:23:22
-
bjne/lua-resty-p8s 0.1.7New string.buffer prometheus metrics module for the ngx_lua module 2023-12-16 10:38:41
-
bjne/lua-resty-p8s 0.1.6New string.buffer prometheus metrics module for the ngx_lua module 2023-12-16 01:43:00
-
bjne/lua-resty-p8s 0.1.5New string.buffer prometheus metrics module for the ngx_lua module 2023-12-16 01:34:42
-
bjne/lua-resty-p8s 0.1.4New string.buffer prometheus metrics module for the ngx_lua module 2023-12-16 00:54:09
-
bjne/lua-resty-p8s 0.1.3New string.buffer prometheus metrics module for the ngx_lua module 2023-12-16 00:14:17
-
bjne/lua-resty-p8s 0.1.2New string.buffer prometheus metrics module for the ngx_lua module 2023-12-15 23:45:20
-
bjne/lua-resty-p8s 0.1.1New string.buffer prometheus metrics module for the ngx_lua module 2023-12-15 23:29:44
-
bjne/lua-resty-p8s 0.1.0New string.buffer prometheus metrics module for the ngx_lua module 2023-12-15 21:23:14