132 lines
4.0 KiB
Lua
132 lines
4.0 KiB
Lua
local set_log_level = require("resty.kong.log").set_log_level
|
|
local cjson = require("cjson.safe")
|
|
local constants = require("kong.constants")
|
|
|
|
local LOG_LEVELS = constants.LOG_LEVELS
|
|
local DYN_LOG_LEVEL_KEY = constants.DYN_LOG_LEVEL_KEY
|
|
local DYN_LOG_LEVEL_TIMEOUT_AT_KEY = constants.DYN_LOG_LEVEL_TIMEOUT_AT_KEY
|
|
|
|
local ngx = ngx
|
|
local kong = kong
|
|
local pcall = pcall
|
|
local type = type
|
|
local tostring = tostring
|
|
local tonumber = tonumber
|
|
|
|
local get_log_level = require("resty.kong.log").get_log_level
|
|
|
|
local NODE_LEVEL_BROADCAST = false
|
|
local CLUSTER_LEVEL_BROADCAST = true
|
|
local DEFAULT_LOG_LEVEL_TIMEOUT = 60 -- 60s
|
|
|
|
|
|
local function handle_put_log_level(self, broadcast)
|
|
if kong.configuration.database == "off" then
|
|
local message = "cannot change log level when not using a database"
|
|
return kong.response.exit(405, { message = message })
|
|
end
|
|
|
|
local log_level = LOG_LEVELS[self.params.log_level]
|
|
local timeout = math.ceil(tonumber(self.params.timeout) or DEFAULT_LOG_LEVEL_TIMEOUT)
|
|
|
|
if type(log_level) ~= "number" then
|
|
return kong.response.exit(400, { message = "unknown log level: " .. self.params.log_level })
|
|
end
|
|
|
|
if timeout < 0 then
|
|
return kong.response.exit(400, { message = "timeout must be greater than or equal to 0" })
|
|
end
|
|
|
|
local cur_log_level = get_log_level()
|
|
|
|
if cur_log_level == log_level then
|
|
local message = "log level is already " .. self.params.log_level
|
|
return kong.response.exit(200, { message = message })
|
|
end
|
|
|
|
local ok, err = pcall(set_log_level, log_level, timeout)
|
|
|
|
if not ok then
|
|
local message = "failed setting log level: " .. err
|
|
return kong.response.exit(500, { message = message })
|
|
end
|
|
|
|
local data = {
|
|
log_level = log_level,
|
|
timeout = timeout,
|
|
}
|
|
|
|
-- broadcast to all workers in a node
|
|
ok, err = kong.worker_events.post("debug", "log_level", data)
|
|
|
|
if not ok then
|
|
local message = "failed broadcasting to workers: " .. err
|
|
return kong.response.exit(500, { message = message })
|
|
end
|
|
|
|
if broadcast then
|
|
-- broadcast to all nodes in a cluster
|
|
ok, err = kong.cluster_events:broadcast("log_level", cjson.encode(data))
|
|
|
|
if not ok then
|
|
local message = "failed broadcasting to cluster: " .. err
|
|
return kong.response.exit(500, { message = message })
|
|
end
|
|
end
|
|
|
|
-- store in shm so that newly spawned workers can update their log levels
|
|
ok, err = ngx.shared.kong:set(DYN_LOG_LEVEL_KEY, log_level, timeout)
|
|
|
|
if not ok then
|
|
local message = "failed storing log level in shm: " .. err
|
|
return kong.response.exit(500, { message = message })
|
|
end
|
|
|
|
ok, err = ngx.shared.kong:set(DYN_LOG_LEVEL_TIMEOUT_AT_KEY, ngx.time() + timeout, timeout)
|
|
|
|
if not ok then
|
|
local message = "failed storing the timeout of log level in shm: " .. err
|
|
return kong.response.exit(500, { message = message })
|
|
end
|
|
|
|
return kong.response.exit(200, { message = "log level changed" })
|
|
end
|
|
|
|
|
|
local routes = {
|
|
["/debug/node/log-level"] = {
|
|
GET = function(self)
|
|
local cur_level = get_log_level()
|
|
|
|
if type(LOG_LEVELS[cur_level]) ~= "string" then
|
|
local message = "unknown log level: " .. tostring(cur_level)
|
|
return kong.response.exit(500, { message = message })
|
|
end
|
|
|
|
return kong.response.exit(200, { message = "log level: " .. LOG_LEVELS[cur_level] })
|
|
end,
|
|
},
|
|
["/debug/node/log-level/:log_level"] = {
|
|
PUT = function(self)
|
|
return handle_put_log_level(self, NODE_LEVEL_BROADCAST)
|
|
end
|
|
},
|
|
}
|
|
|
|
|
|
local cluster_name
|
|
|
|
if kong.configuration.role == "control_plane" then
|
|
cluster_name = "/debug/cluster/control-planes-nodes/log-level/:log_level"
|
|
else
|
|
cluster_name = "/debug/cluster/log-level/:log_level"
|
|
end
|
|
|
|
routes[cluster_name] = {
|
|
PUT = function(self)
|
|
return handle_put_log_level(self, CLUSTER_LEVEL_BROADCAST)
|
|
end
|
|
}
|
|
|
|
return routes
|