lua-resty-dymetrics
重新编译 OpenResty
动态指标模块需要给 Nginx 核心打补丁,因此需要重新编译 OpenResty。 这个补丁我们会通过邮件的方式进行交付。
下面的脚本用于给 OpenResty 1.19.9.1 版本的 Nginx 核心打补丁。 打完补丁后,用户可以根据原来的打包流程进行打包。
set -e
pkg=openresty-1.19.9.1
ngx=nginx-1.19.9
wget https://openresty.org/download/$pkg.tar.gz
tar -xf $pkg.tar.gz
cd $pkg/bundle/$ngx/
patch -p1 < ../../../nginx-1.19.9-proc_exit_handler.patch
cd ../../..
tar -czf $pkg.tar.gz $pkg
配置二进制安装包仓库
首先我们需要配置二进制安装包的仓库,按照以下命令进行配置。(命令中的 CLIENT_TOKEN
需要替换成订阅邮件中的有效 Token)
curl -o get-xray-priv-lib-repo.sh https://pkg2.openresty.com.cn/scripts/get-xray-priv-lib-repo.sh
sudo bash get-xray-priv-lib-repo.sh -l lua-resty-dymetrics-(customer-name) -t CLIENT_TOKEN
sudo bash get-xray-priv-lib-repo.sh -l dymetrics-nginx-module -t CLIENT_TOKEN
sudo bash get-xray-priv-lib-repo.sh -l openresty-priv-comm -t CLIENT_TOKEN
安装软件包
动态指标需要安装如下四个组件
- openresty-yajl
- openresty-yajl-devel
- dymetrics-nginx-module
- lua-resty-dymetrics-(customer-name)
其中,lua-resty-dymetrics-(customer-name) 这个组件可以根据客户定制, 因此不同的客户需要根据自己的名称安装响应的组件。下面命令中的 customer-name 需要根据实际情况进行替换。
使用 yum
包管理器的操作系统,执行以下命令进行私有库的安装。
sudo yum install -y dymetrics-nginx-module-1.19.9 openresty-yajl openresty-yajl-devel
sudo yum install -y lua-resty-dymetrics-(customer-name)
使用 dnf
包管理器的操作系统,执行以下命令进行私有库的安装。
sudo dnf install -y dymetrics-nginx-module-1.19.9 openresty-yajl openresty-yajl-devel
sudo dnf install -y lua-resty-dymetrics-(customer-name)
使用 apt
包管理器的操作系统,执行以下命令进行私有库的安装。
sudo apt-get install -y dymetrics-nginx-module-1.19.9 openresty-yajl openresty-yajl-dev
sudo apt-get install -y lua-resty-dymetrics-(customer-name)
使用
在使用前需要在配置文件 nginx.conf
中需要添加以下这些配置项。
- load_module 指令用于加载
ngx_http_lua_dymetrics_module
这个动态模块。 - lua_package_path 和 lua_package_cpath 指令 指定 lua 文件和 lua 加载的二进制共享库搜索路径。
- lua_shared_dymetrics 这个指令定义一个动态指标使用的共享内存区。
load_module /usr/local/openresty/nginx/lib/ngx_http_lua_dymetrics_module.so;
http {
lua_package_path "/usr/local/openresty/site/lualib/?.ljbc;;";
lua_package_cpath "/usr/local/openresty-yajl/lib/?.so;/usr/local/openresty/site/lualib/?.so;;";
lua_shared_dymetrics dymetrics 120M;
}
server {
listen 80;
server_name localhost;
set $app_uid "test.openresty.com";
log_by_lua_block {
if ngx.ctx.no_dymetrics_log then
return
end
local ts = ngx.time()
ts = ts - (ts % 60)
local request_log = require "resty.dymetrics_http_reqs".request_log
local conn_log= require "resty.dymetrics_http_conns".request_log
local lua_vars = {}
local app_id = 0
request_log(ts, app_id, lua_vars)
conn_log(ts, app_id, lua_vars)
}
location /metrics {
allow 127.0.0.1;
allow 18.140.243.108; # just an example
deny all;
content_by_lua_block {
ngx.ctx.no_dymetrics_log = true
local report_req_data = require "resty.dymetrics_http_reqs".report_data_prometheus
local report_conn_data = require "resty.dymetrics_http_conns".report_data_prometheus
local ts = ngx.time()
ts = ts - 60 - (ts % 60)
local data, err = report_req_data(ts, 0, "")
if err ~= nil then
ngx.log(ngx.ERR, "prometheus: failed to get http request data:", err)
else
ngx.say(data)
end
local data, err = report_conn_data(ts, 0, "")
if err ~= nil then
ngx.log(ngx.ERR, "prometheus: failed to get http connection data:", err)
else
ngx.say(data)
end
}
}
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
Lua APIs
dymetrics_http_reqs module
request_log
syntax: ok, err = reqs.request_log(time_key, app_id, lua_variables)
context: log_by_lua*
Calling this interface will add the current request to the statistics. If there is an error, it will return nil and the corresponding error message.
The value of time_key
is the starting value of the statistics cycle. For example, if 60s is a statistics cycle, then “time_key” can be obtained as follows: time_key = ngx.time() - ngx.time() % 60
. app_id
is a key for Prometheus output. If app_id is not distinguished, pass value 0
. lua_variables
is an extension variable that is currently not used and requires passing an empty Lua table.
Here is an example:
log_by_lua_block {
local ts = ngx.time()
ts = ts - (ts % 60)
local request_log = require "resty.dymetrics_http_reqs".request_log
local lua_vars = {}
local app_id = 0
request_log(ts, app_id, lua_vars)
}
report_data
syntax: ok, err = reqs. report_data(time_key, node_id, partition_id, gateway_id)
context: content_by_lua_block*,ngx.timer.*
Get the dynamic indicators for the statistics cycle that starts with time_key
. This time_key
is for the previous statistics cycle, not the current one, because the current statistics cycle has not yet ended, and new requests will still be added to it.
node_id
represents the current machine’s ID. If it does not exist, it should be passed as 0.
partition_id
is a string representing the current partition’s ID. If it does not exist, it can be passed as nil
. gateway_id
is the ID of the gateway that the current node belongs to. If it does not exist, it can be passed as nil
.
Here is an example:
content_by_lua_block {
local report_req_data = require "resty.dymetrics_http_reqs".report_data
local ts = ngx.time()
ts = ts - 60 - (ts % 60)
local data, err = report_req_data(ts, 0, "")
if err ~= nil then
ngx.log(ngx.ERR, "prometheus: failed to get http request data:", err)
else
ngx.say(data)
end
}
report_data_prometheus
syntax: ok, err = reqs.report_data_prometheus(time_key, node_id, partition_id, gateway_id)
context: content_by_lua_block*,ngx.timer.*
Get the dynamic indicators for the statistics cycle that starts with time_key
. This time_key
is for the previous statistics cycle, not the current one, because the current statistics cycle has not yet ended, and new requests will still be added to it.
node_id
represents the current machine’s ID. If it does not exist, it should be passed as 0.
partition_id
is a string representing the current partition’s ID. If it does not exist, it can be passed as nil
. gateway_id
is the ID of the gateway that the current node belongs to. If it does not exist, it can be passed as nil
.
Here is an example:
content_by_lua_block {
local report_req_data = require "resty.dymetrics_http_reqs".report_data_prometheus
local ts = ngx.time()
ts = ts - 60 - (ts % 60)
local data, err = report_req_data(ts, 0, "")
if err ~= nil then
ngx.log(ngx.ERR, "prometheus: failed to get http request data:", err)
else
ngx.say(data)
end
}
dymetrics_http_conns module
request_log
syntax: ok, err = conns.request_log(time_key, app_id, lua_variables)
context: log_by_lua*
Calling this interface will add the current request to the statistics. If there is an error, it will return nil and the corresponding error message.
The value of time_key
is the starting value of the statistics cycle. For example, if 60s is a statistics cycle, then “time_key” can be obtained as follows: time_key = ngx.time() - ngx.time() % 60
. app_id
is a key for Prometheus output. If app_id is not distinguished, pass value 0
. lua_variables
is an extension variable that is currently not used and requires passing an empty Lua table.
Here is an example:
log_by_lua_block {
local ts = ngx.time()
ts = ts - (ts % 60)
local conn_log = require "resty.dymetrics_http_conns".request_log
local lua_vars = {}
local app_id = 0
request_log(ts, app_id, lua_vars)
}
report_data
syntax: ok, err = conns.report_data(time_key, node_id, partition_id, gateway_id)
context: content_by_lua_block*,ngx.timer.*
Get the dynamic indicators for the statistics cycle that starts with time_key
. This time_key
is for the previous statistics cycle, not the current one, because the current statistics cycle has not yet ended, and new requests will still be added to it.
node_id
represents the current machine’s ID. If it does not exist, it should be passed as 0.
partition_id
is a string representing the current partition’s ID. If it does not exist, it can be passed as nil
. gateway_id
is the ID of the gateway that the current node belongs to. If it does not exist, it can be passed as nil
.
Here is an example:
content_by_lua_block {
local report_req_data = require "resty.dymetrics_http_conns".report_data
local ts = ngx.time()
ts = ts - 60 - (ts % 60)
local data, err = report_req_data(ts, 0, "")
if err ~= nil then
ngx.log(ngx.ERR, "prometheus: failed to get http request data:", err)
else
ngx.say(data)
end
}
report_data_prometheus
syntax: ok, err = conns.report_data_prometheus(time_key, node_id, partition_id, gateway_id)
context: content_by_lua_block*,ngx.timer.*
Get the dynamic indicators for the statistics cycle that starts with time_key
. This time_key
is for the previous statistics cycle, not the current one, because the current statistics cycle has not yet ended, and new requests will still be added to it.
node_id
represents the current machine’s ID. If it does not exist, it should be passed as 0.
partition_id
is a string representing the current partition’s ID. If it does not exist, it can be passed as nil
. gateway_id
is the ID of the gateway that the current node belongs to. If it does not exist, it can be passed as nil
.
Here is an example:
content_by_lua_block {
local report_req_data = require "resty.dymetrics_http_conns".report_data_prometheus
local ts = ngx.time()
ts = ts - 60 - (ts % 60)
local data, err = report_req_data(ts, 0, "")
if err ~= nil then
ngx.log(ngx.ERR, "prometheus: failed to get http request data:", err)
else
ngx.say(data)
end
}