apisix icon indicating copy to clipboard operation
apisix copied to clipboard

help request: How to expose custom Prometheus metric with custom plugin

Open br41n10 opened this issue 1 year ago • 1 comments

Description

How to expose a metric from custom plugin, using the default prometheus exported URI /apisix/prometheus/metrics.

In my case, I want get summary metric about request_time, not the builtin histogram metric apisix_http_latency_bucket. I don't know what is the best practice to achieve this.

Here is my try

local base_prometheus = require("prometheus")
local core = require("apisix.core")
local ngx       = ngx
local clear_tab = core.table.clear
local plugin_name = "request-time-metric"
local prometheus = require("apisix.plugins.prometheus.exporter")

local custom_metrics = {}

local schema = {
    type = "object",
    properties = {},
}

local _M = {
    version = 0.1,
    priority = 40,
    name = plugin_name,
    schema = schema,
}

-- need modify ngx_tpl.lua to call this function, I don't think this is a better way
function _M.http_init()
    if ngx.get_phase() ~= "init" and ngx.get_phase() ~= "init_worker"  then
        return
    end

    clear_tab(custom_metrics)

    prometheus = base_prometheus.init("prometheus-metrics", "apisix_")

    custom_metrics.test_counter = prometheus:counter("test_counter", "test", {"test"})
end

function _M.http_log(conf, ctx)
    custom_metrics.test_counter:inc(1, "test")
end

function _M.log(conf, ctx)
    -- print "null"
    core.log.warn("metrics: ", core.json.encode(custom_metrics.test_counter, true))
end

return _M

Seems I need to modify ngx_tpl.lua to call http_init, but from docs, this is not recommend.

Is this the right way? Or should I just modify the builtin prometheus/exporter.lua plugin (is there will be a problem when upgrade apisix?) ?

Environment

  • APISIX version (run apisix version): 3.9.1
  • OpenResty / Nginx version (run openresty -V or nginx -V): openresty/1.25.3.1

br41n10 avatar Jun 14 '24 05:06 br41n10

just do it in the plugin:

local exporter = require("apisix.plugins.prometheus.exporter")

local metric_api_requests_total

function _M.init()
    prometheus_registry = exporter.get_prometheus()

    -- registers  metrics.
    metric_api_requests_total = prometheus_registry:counter(
        "api_requests_total",
        "How many HTTP requests processed, partitioned by status code, method and HTTP path.", {
            "label1",
            "label2",
            ......
        }
    )
end


function _M.log(conf, ctx)
    metric_api_requests_total:inc(
        1, {
            label_value_1,
            label_value_2,
            ......
        }
    )
end

wklken avatar Oct 18 '24 07:10 wklken

If there is still a problem, please open it again.

Baoyuantop avatar May 14 '25 03:05 Baoyuantop