diff --git a/kong/reports.lua b/kong/reports.lua index 302fb0054a19..69ecd9b1b692 100644 --- a/kong/reports.lua +++ b/kong/reports.lua @@ -49,6 +49,7 @@ local KM_VISIT_COUNT_KEY = "events:km:visit" local GO_PLUGINS_REQUEST_COUNT_KEY = "events:requests:go_plugins" +local WASM_REQUEST_COUNT_KEY = "events:requests:wasm" local ROUTE_CACHE_HITS_KEY = "route_cache_hits" @@ -314,6 +315,7 @@ local function send_ping(host, port) _ping_infos.udp_streams = get_counter(UDP_STREAM_COUNT_KEY) _ping_infos.tls_streams = get_counter(TLS_STREAM_COUNT_KEY) _ping_infos.go_plugin_reqs = get_counter(GO_PLUGINS_REQUEST_COUNT_KEY) + _ping_infos.wasm_reqs = get_counter(WASM_REQUEST_COUNT_KEY) _ping_infos.stream_route_cache_hit_pos = get_counter(STEAM_ROUTE_CACHE_HITS_KEY_POS) _ping_infos.stream_route_cache_hit_neg = get_counter(STEAM_ROUTE_CACHE_HITS_KEY_NEG) @@ -325,6 +327,7 @@ local function send_ping(host, port) reset_counter(UDP_STREAM_COUNT_KEY, _ping_infos.udp_streams) reset_counter(TLS_STREAM_COUNT_KEY, _ping_infos.tls_streams) reset_counter(GO_PLUGINS_REQUEST_COUNT_KEY, _ping_infos.go_plugin_reqs) + reset_counter(WASM_REQUEST_COUNT_KEY, _ping_infos.wasm_reqs) reset_counter(STEAM_ROUTE_CACHE_HITS_KEY_POS, _ping_infos.stream_route_cache_hit_pos) reset_counter(STEAM_ROUTE_CACHE_HITS_KEY_NEG, _ping_infos.stream_route_cache_hit_neg) return @@ -341,6 +344,7 @@ local function send_ping(host, port) _ping_infos.wss_reqs = get_counter(WSS_REQUEST_COUNT_KEY) _ping_infos.km_visits = get_counter(KM_VISIT_COUNT_KEY) _ping_infos.go_plugin_reqs = get_counter(GO_PLUGINS_REQUEST_COUNT_KEY) + _ping_infos.wasm_reqs = get_counter(WASM_REQUEST_COUNT_KEY) _ping_infos.request_route_cache_hit_pos = get_counter(REQUEST_ROUTE_CACHE_HITS_KEY_POS) _ping_infos.request_route_cache_hit_neg = get_counter(REQUEST_ROUTE_CACHE_HITS_KEY_NEG) @@ -358,6 +362,7 @@ local function send_ping(host, port) reset_counter(WSS_REQUEST_COUNT_KEY, _ping_infos.wss_reqs) reset_counter(KM_VISIT_COUNT_KEY, _ping_infos.km_visits) reset_counter(GO_PLUGINS_REQUEST_COUNT_KEY, _ping_infos.go_plugin_reqs) + reset_counter(WASM_REQUEST_COUNT_KEY, _ping_infos.wasm_reqs) reset_counter(REQUEST_ROUTE_CACHE_HITS_KEY_POS, _ping_infos.request_route_cache_hit_pos) reset_counter(REQUEST_ROUTE_CACHE_HITS_KEY_NEG, _ping_infos.request_route_cache_hit_neg) end @@ -480,6 +485,10 @@ return { incr_counter(GO_PLUGINS_REQUEST_COUNT_KEY) end + if ctx.ran_wasm then + incr_counter(WASM_REQUEST_COUNT_KEY) + end + local suffix = get_current_suffix(ctx) if suffix then incr_counter(count_key .. ":" .. suffix) diff --git a/kong/runloop/wasm.lua b/kong/runloop/wasm.lua index 52eac439db48..d9a10ca4aecc 100644 --- a/kong/runloop/wasm.lua +++ b/kong/runloop/wasm.lua @@ -2,6 +2,7 @@ local _M = {} local utils = require "kong.tools.utils" local dns = require "kong.tools.dns" +local reports = require "kong.reports" local clear_tab = require "table.clear" ---@module 'resty.wasmx.proxy_wasm' @@ -530,6 +531,8 @@ function _M.init(kong_config) return end + reports.add_immutable_value("wasm_cnt", #modules) + -- setup a DNS client for ngx_wasm_module _G.dns_client = dns(kong_config) @@ -590,6 +593,8 @@ function _M.attach(ctx) return end + ctx.ran_wasm = true + local ok, err = proxy_wasm.attach(chain.c_plan, ATTACH_OPTS) if not ok then log(CRIT, "failed attaching ", chain.label, " filter chain to request: ", err) diff --git a/spec/02-integration/20-wasm/07-reports_spec.lua b/spec/02-integration/20-wasm/07-reports_spec.lua new file mode 100644 index 000000000000..0051d41ae2ec --- /dev/null +++ b/spec/02-integration/20-wasm/07-reports_spec.lua @@ -0,0 +1,120 @@ +local helpers = require "spec.helpers" +local constants = require "kong.constants" +local cjson = require "cjson" + + +local function json(body) + return { + headers = { ["Content-Type"] = "application/json" }, + body = body, + } +end + + +for _, strategy in helpers.each_strategy() do + local dns_hostsfile + local reports_server + + describe("anonymous reports for Wasm #" .. strategy, function() + local reports_send_ping = function(port) + ngx.sleep(0.2) -- hand over the CPU so other threads can do work (processing the sent data) + local admin_client = helpers.admin_client() + local res = admin_client:post("/reports/send-ping" .. (port and "?port=" .. port or "")) + assert.response(res).has_status(200) + admin_client:close() + end + + lazy_setup(function() + dns_hostsfile = assert(os.tmpname() .. ".hosts") + local fd = assert(io.open(dns_hostsfile, "w")) + assert(fd:write("127.0.0.1 " .. constants.REPORTS.ADDRESS)) + assert(fd:close()) + + local bp, db = assert(helpers.get_db_utils(strategy, { + "services", + "routes", + "plugins", + }, { "reports-api" })) + + local http_srv = assert(bp.services:insert { + name = "mock-service", + host = helpers.mock_upstream_host, + port = helpers.mock_upstream_port, + }) + + bp.routes:insert({ service = http_srv, + protocols = { "http" }, + hosts = { "http-service.test" }}) + + bp.plugins:insert({ + name = "reports-api", + config = {} + }) + + db.filter_chains:load_filters({ + { name = "tests" }, + }) + + assert(helpers.start_kong({ + nginx_conf = "spec/fixtures/custom_nginx.template", + database = strategy, + dns_hostsfile = dns_hostsfile, + plugins = "bundled,reports-api", + wasm = true, + anonymous_reports = true, + })) + + local admin = assert(helpers.admin_client()) + local res = admin:post("/filter-chains", json({ + filters = { { name = "tests" } }, + service = { id = http_srv.id }, + }) + ) + assert.res_status(201, res) + admin:close() + end) + + lazy_teardown(function() + os.remove(dns_hostsfile) + + helpers.stop_kong() + end) + + before_each(function() + reports_server = helpers.tcp_server(constants.REPORTS.STATS_TLS_PORT, {tls=true}) + end) + + it("logs number of enabled Wasm filters", function() + reports_send_ping(constants.REPORTS.STATS_TLS_PORT) + + local _, reports_data = assert(reports_server:join()) + reports_data = cjson.encode(reports_data) + + assert.match("wasm_cnt=2", reports_data) + end) + + it("logs number of requests triggering a Wasm filter", function() + local proxy_client = assert(helpers.proxy_client()) + local res = proxy_client:get("/", { + headers = { host = "http-service.test" } + }) + assert.res_status(200, res) + + local proxy_client2 = assert(helpers.proxy_client()) + local res = proxy_client2:get("/", { + headers = { host = "http-service.test" } + }) + assert.res_status(200, res) + + reports_send_ping(constants.REPORTS.STATS_TLS_PORT) + + local _, reports_data = assert(reports_server:join()) + reports_data = cjson.encode(reports_data) + + assert.match("wasm_reqs=2", reports_data) + proxy_client:close() + proxy_client2:close() + end) + + end) +end