local helpers = require "spec.helpers" local UUID_PATTERN = "%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x" local function get_metrics(client) local res = assert(client:send { method = "GET", path = "/metrics", }) return assert.res_status(200, res) end local function assert_normal_metrics(body) -- normal fields assert.matches('kong_memory_lua_shared_dict_bytes', body, nil, true) local states = { "accepted", "active", "handled", "reading", "total", "waiting", "writing" } for _, v in ipairs(states) do assert.matches('kong_nginx_connections_total{node_id="' .. UUID_PATTERN .. '",subsystem="' .. ngx.config.subsystem .. '",state="' .. v .. '"} %d+', body) end end local high_cost_metrics = { "kong_http_requests_total", "kong_kong_latency_ms", "kong_upstream_latency_ms", "kong_request_latency_ms", "kong_bandwidth_bytes", } for _, strategy in helpers.each_strategy() do describe("Plugin: prometheus, on-demond export metrics #" .. strategy, function() local http_client, status_client local prometheus_id local tcp_status_port lazy_setup(function() tcp_status_port = helpers.get_available_port() end) -- restart the kong every time or the test would be flaky before_each(function() -- remember to truncate the tables so it won't be flaky! local bp = assert(helpers.get_db_utils(strategy, { "upstreams", "targets", "services", "routes", "plugins", })) local upstream = bp.upstreams:insert({ name = "mock_upstream", algorithm = "least-connections", }) bp.targets:insert({ upstream = upstream, target = helpers.mock_upstream_host .. ":" .. helpers.mock_upstream_port, weight = 100, }) local service = bp.services:insert { host = "mock_upstream", } bp.routes:insert { hosts = { "mock" }, protocols = { "http" }, service = service, paths = { "/" }, } prometheus_id = assert(bp.plugins:insert { name = "prometheus", config = { status_code_metrics = true, latency_metrics = true, bandwidth_metrics = true, upstream_health_metrics = true, } }).id assert(helpers.start_kong { nginx_conf = "spec/fixtures/custom_nginx.template", plugins = "bundled", database = strategy, cluster_cert = "spec/fixtures/ocsp_certs/kong_clustering.crt", cluster_cert_key = "spec/fixtures/ocsp_certs/kong_clustering.key", status_listen = "0.0.0.0:" .. tcp_status_port, proxy_listen = "0.0.0.0:8000", db_cache_ttl = 100, -- so the cache won't expire while we wait for the admin API }) http_client = helpers.http_client("127.0.0.1", 8000, 20000) status_client = helpers.http_client("127.0.0.1", tcp_status_port, 20000) -- C* is so slow we need to wait helpers.pwait_until(function() assert.res_status(200, http_client:send { method = "GET", path = "/", headers = { ["Host"] = "mock" } }) end) end) after_each(function() helpers.stop_kong() if http_client then http_client:close() end if status_client then status_client:close() end end) for _, method in ipairs { "disabling", "removing" } do it("less metrics when " .. method .. " prometheus", function() -- export normal metrics local body = get_metrics(status_client) assert_normal_metrics(body) for _, v in ipairs(high_cost_metrics) do assert.matches(v, body, nil, true) end -- disable or remove local admin_client = helpers.admin_client() if method == "disabling" then assert.res_status(200, admin_client:send { method = "PATCH", path = "/plugins/" .. prometheus_id, body = { enabled = false, }, headers = { ["Content-Type"] = "application/json" } }) else assert.res_status(204, admin_client:send { method = "DELETE", path = "/plugins/" .. prometheus_id, }) end helpers.pwait_until(function() body = get_metrics(status_client) assert_normal_metrics(body) for _, v in ipairs(high_cost_metrics) do assert.not_matches(v, body, nil, true) end end, 5) end) end end) end