Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(api) support HTTP/2 status and metrics requests #8687

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions kong/api/routes/health.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
local utils = require "kong.tools.utils"
local declarative = require "kong.db.declarative"
local http = require "resty.http"

local find = string.find
local select = select
Expand All @@ -14,6 +15,7 @@ local tonumber = tonumber
local kong = kong
local dbless = kong.configuration.database == "off"
local data_plane_role = kong.configuration.role == "data_plane"
local nginx_status_sock = "unix:" .. ngx.config.prefix() .. "nginx_status.sock"


return {
Expand Down Expand Up @@ -42,14 +44,27 @@ return {

-- nginx stats

local r = ngx.location.capture "/nginx_status"
local httpc = http.new()
local _, err = httpc:connect(nginx_status_sock)
if err ~= nil then
kong.log.err("failed to retrieve status: ", err)
return kong.response.exit(500, { message = "An unexpected error happened" })
end
local r, err = httpc:request({ method = "GET", path = "/nginx_status",
headers = { ["Host"] = "localhost" } })
local nginx_status_body = r:read_body()
httpc:close()
if err ~= nil then
kong.log.err("failed to retrieve status: ", err)
return kong.response.exit(500, { message = "An unexpected error happened" })
end
if r.status ~= 200 then
kong.log.err(r.body)
kong.log.err("failed to retrieve status: ", nginx_status_body)
return kong.response.exit(500, { message = "An unexpected error happened" })
end

local var = ngx.var
local accepted, handled, total = select(3, find(r.body, "accepts handled requests\n (%d*) (%d*) (%d*)"))
local accepted, handled, total = select(3, find(nginx_status_body, "accepts handled requests\n (%d*) (%d*) (%d*)"))

local status_response = {
memory = knode.get_memory_stats(unit, scale),
Expand Down
36 changes: 26 additions & 10 deletions kong/plugins/prometheus/exporter.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ local find = string.find
local lower = string.lower
local concat = table.concat
local select = select
local http = require "resty.http"
local ngx_timer_pending_count = ngx.timer.pending_count
local ngx_timer_running_count = ngx.timer.running_count
local balancer = require("kong.runloop.balancer")
Expand All @@ -12,6 +13,8 @@ if not balancer.get_all_upstreams then -- API changed since after Kong 2.5
get_all_upstreams = require("kong.runloop.balancer.upstreams").get_all_upstreams
end

local nginx_status_sock = "unix:" .. ngx.config.prefix() .. "nginx_status.sock"

local CLUSTERING_SYNC_STATUS = require("kong.constants").CLUSTERING_SYNC_STATUS

local stream_available, stream_api = pcall(require, "kong.tools.stream_api")
Expand Down Expand Up @@ -298,18 +301,31 @@ local function metric_data()
end

if ngx.location then
local r = ngx.location.capture "/nginx_status"

if r.status ~= 200 then
local httpc = http.new()
local _, err = httpc:connect(nginx_status_sock)
if err ~= nil then
kong.log.warn("prometheus: failed to retrieve /nginx_status ",
"while processing /metrics endpoint")

"while processing /metrics endpoint: ", err)
else
local accepted, handled, total = select(3, find(r.body,
"accepts handled requests\n (%d*) (%d*) (%d*)"))
metrics.connections:set(accepted, { "accepted" })
metrics.connections:set(handled, { "handled" })
metrics.connections:set(total, { "total" })
local r, err = httpc:request({ method = "GET", path = "/nginx_status",
headers = { ["Host"] = "localhost" } })
local nginx_status_body = r:read_body()
httpc:close()
if err ~= nil then
kong.log.warn("prometheus: failed to retrieve /nginx_status ",
"while processing /metrics endpoint: ", err)

elseif r.status ~= 200 then
kong.log.warn("prometheus: failed to retrieve /nginx_status ",
"while processing /metrics endpoint")

else
local accepted, handled, total = select(3, find(nginx_status_body,
"accepts handled requests\n (%d*) (%d*) (%d*)"))
metrics.connections:set(accepted, { "accepted" })
metrics.connections:set(handled, { "handled" })
metrics.connections:set(total, { "total" })
end
end
end

Expand Down
24 changes: 12 additions & 12 deletions kong/templates/nginx_kong.lua
Original file line number Diff line number Diff line change
Expand Up @@ -363,12 +363,6 @@ server {
}
}

location /nginx_status {
internal;
access_log off;
stub_status;
}

location /robots.txt {
return 200 'User-agent: *\nDisallow: /';
}
Expand Down Expand Up @@ -408,18 +402,24 @@ server {
}
}

location /nginx_status {
internal;
access_log off;
stub_status;
}

location /robots.txt {
return 200 'User-agent: *\nDisallow: /';
}
}
> end

> if #status_listeners > 0 or (#admin_listeners > 0 and (role == "control_plane" or role == "traditional")) then
server {
server_name nginx_status;
listen unix:${{PREFIX}}/nginx_status.sock;
error_log ${{ADMIN_ERROR_LOG}} ${{LOG_LEVEL}};
location /nginx_status {
access_log off;
stub_status;
}
}
> end -- #status_listeners > 0 or (#admin_listeners > 0 and (role == "control_plane" or role == "traditional"))

> if role == "control_plane" then
server {
server_name kong_cluster_listener;
Expand Down
9 changes: 9 additions & 0 deletions spec/02-integration/02-cmd/02-start_stop_spec.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
local helpers = require "spec.helpers"
local pl_path = require "pl.path"


for _, strategy in helpers.each_strategy() do
Expand All @@ -11,6 +12,14 @@ describe("kong start/stop #" .. strategy, function()
}) -- runs migrations
helpers.prepare_prefix()
end)
before_each(function()
helpers.wait_until(function()
if pl_path.exists(helpers.test_conf.prefix .. "/nginx_status.sock") then
return false
end
return true
end, 10)
end)
after_each(function()
helpers.kill_all()
end)
Expand Down
2 changes: 1 addition & 1 deletion spec/02-integration/04-admin_api/01-admin_api_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ describe("Admin API listeners", function()
admin_listen = "127.0.0.1:9001, 127.0.0.1:9002",
}))

assert.equals(2, count_server_blocks(helpers.test_conf.nginx_kong_conf))
assert.equals(3, count_server_blocks(helpers.test_conf.nginx_kong_conf))
assert.same({
["127.0.0.1:9001"] = 1,
["127.0.0.1:9002"] = 2,
Expand Down
4 changes: 2 additions & 2 deletions spec/02-integration/05-proxy/01-proxy_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ describe("Proxy interface listeners", function()
proxy_listen = "off",
admin_listen = "0.0.0.0:9001",
}))
assert.equals(1, count_server_blocks(helpers.test_conf.nginx_kong_conf))
assert.equals(2, count_server_blocks(helpers.test_conf.nginx_kong_conf))
assert.is_nil(get_listeners(helpers.test_conf.nginx_kong_conf).kong)
end)

Expand All @@ -53,7 +53,7 @@ describe("Proxy interface listeners", function()
admin_listen = "0.0.0.0:9000",
}))

assert.equals(2, count_server_blocks(helpers.test_conf.nginx_kong_conf))
assert.equals(3, count_server_blocks(helpers.test_conf.nginx_kong_conf))
assert.same({
["127.0.0.1:9001"] = 1,
["127.0.0.1:9002"] = 2,
Expand Down
23 changes: 11 additions & 12 deletions spec/fixtures/custom_nginx.template
Original file line number Diff line number Diff line change
Expand Up @@ -385,12 +385,6 @@ http {
}
}

location /nginx_status {
internal;
access_log off;
stub_status;
}

location /robots.txt {
return 200 'User-agent: *\nDisallow: /';
}
Expand Down Expand Up @@ -430,18 +424,23 @@ http {
}
}

location /nginx_status {
internal;
access_log off;
stub_status;
}

location /robots.txt {
return 200 'User-agent: *\nDisallow: /';
}
}
> end

> if #status_listeners > 0 or (#admin_listeners > 0 and (role == "control_plane" or role == "traditional")) then
server {
listen unix:${{PREFIX}}/nginx_status.sock;
error_log ${{ADMIN_ERROR_LOG}} ${{LOG_LEVEL}};
location /nginx_status {
access_log off;
stub_status;
}
}
> end -- #status_listeners > 0 or (#admin_listeners > 0 and (role == "control_plane" or role == "traditional"))

> if role == "control_plane" then
server {
server_name kong_cluster_listener;
Expand Down