动态指标

以往我们做一些服务器上的指标数据统计,比如某个域名的访问量最高的 10 个客户端地址,某个域名的缓存命中率,则需要服务器将全量的指标数据上报到监控系统,再在监控系统中数据的聚合计算。

而动态指标功能支持以类似 SQL 语法的 Metric SQL 编写聚合规则,在服务器上高效地实时聚合计算得到统计数据,大大地减少了需要上报的数据量。Metric SQL 的语法可以参考这个文档:Metric SQL

动态指标的统计数据目前支持以 Lua API 和 Prometheus Exporter 的方式导出。

这里我们提供一个统计请求状态码分布的实际例子。

创建动态指标

选择新建动态指标,名称填写为 status-distribution,指标聚合上报间隔为 60 秒,SQL 内容如下:

select count(*) from reqs group by status;

导出动态指标

点击编译按钮,然后可以从下面的编译历史中下载编译后的 zip 压缩包。

压缩包中包含以下这些文件,解压后复制到 nginx.conf 中指定的 lua_package_path 目录下。

Archive:  Tool-1-dymetrics-status-distribution.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
     2383  01-26-2022 17:12   dymetrics.ljbc
        0  01-26-2022 17:12   metrics/
    59638  01-26-2022 17:12   metrics/status-distribution.ljbc

此外,在列表页也可以通过多选的方式来导出多个动态指标。

修改 nginx.conf 配置

动态指标需要修改 nginx.conf 配置才能使用,在 http block 内添加动态指标配置,示例是推荐配置的大小,可以根据实际情况调整。同时动态指标还依赖 openresty-yajl,还需要在 lua_package_cpath 加上 openresty-yajl 的路径。

lua_shared_dict dymetrics_keys 1m;
lua_shared_dymetrics dymetrics 100m;
lua_package_cpath "/usr/local/openresty-yajl/lib64/;./?.so;;";

添加动态指标初始化代码

init_worker 阶段进行初始化,需要提供一个回调函数。指标每个统计周期完成后会调用这个函数,在这里将统计数据回传。

init_worker_by_lua_block {
   local report_func = function (data)
       -- `data` is the result of the metric statistics
   end

   require "dymetrics" .init_worker(report_func)
}

添加动态指标采集入口

log_by_lua_block 阶段添加采集入口。

log_by_lua_block {
    require "dymetrics" .collect()
}

添加 Prometheus Exporter 接口

Prometheus 的数据可以从这个接口导出。

location /prometheus {
    content_by_lua_block {
        require "dymetrics" .prometheus()
    }
}

完整的 nginx.conf

worker_processes  auto;

events {
    worker_connections  1024;
}

http {
    lua_package_path "$prefix/lua/?.lua;;";
    lua_package_cpath "$prefix/lualib/?.so;/usr/local/openresty-yajl/lib64/?.so;;";

    sendfile        on;
    keepalive_timeout  65;

    lua_shared_dict dymetric_version 1m;
    lua_shared_dymetrics dymetrics 100m;

    init_worker_by_lua_block {
        local report_func = function (data)
            -- do nothing
        end

        require "dymetrics" .init_worker(report_func)
    }

    server {
        listen       127.0.0.1:80;
        server_name  localhost;

        location / {
            root   html;
            index  index.html index.htm;

            log_by_lua_block {
                require "dymetrics" .collect()
            }
        }

        location /prometheus {
            content_by_lua_block {
                require "dymetrics" .prometheus()
            }
        }
    }
}