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

feat(debug-mode): add dynamic debug mode #5012

Merged
merged 27 commits into from Sep 22, 2021
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b395a9e
feat(debug-mode): add dynamic debug mode
tzssangglass Sep 7, 2021
dbf2bb6
remove unused variable pairs
tzssangglass Sep 7, 2021
6b5ddaf
remove blank lines
tzssangglass Sep 7, 2021
dc5c2ba
fix IC error
tzssangglass Sep 8, 2021
48849d4
refactor
tzssangglass Sep 12, 2021
4480d39
remove lua_shared_dict in config-default.yaml
tzssangglass Sep 12, 2021
c28bb08
fix CI error
tzssangglass Sep 12, 2021
c85ce13
fix CI error
tzssangglass Sep 12, 2021
60d255d
fix CI error
tzssangglass Sep 12, 2021
67d39f9
chore the require ngx.process to function in debug.lua
tzssangglass Sep 13, 2021
dc9c202
save
tzssangglass Sep 14, 2021
0261e83
Merge branch 'master' of https://github.com/apache/apisix into edbh
tzssangglass Sep 14, 2021
480dc74
save
tzssangglass Sep 15, 2021
01c35d9
refactor the way of dynamic debug
tzssangglass Sep 15, 2021
6b17805
fix code lint
tzssangglass Sep 15, 2021
1f58c6f
remove unnecessary judgement conditions
tzssangglass Sep 15, 2021
bca20cc
chore require
tzssangglass Sep 15, 2021
bdd63ba
fix CI error
tzssangglass Sep 15, 2021
fd123a3
refactor dynamic hook enable logic
tzssangglass Sep 15, 2021
7ae81f4
fix code lint
tzssangglass Sep 15, 2021
e4d16b2
resolve code review
tzssangglass Sep 17, 2021
e919b6d
Merge branch 'master' of https://github.com/apache/apisix into edbh
tzssangglass Sep 17, 2021
58ec3f9
merge master
tzssangglass Sep 17, 2021
e47e0a4
fix Ci error
tzssangglass Sep 17, 2021
3f40625
fix code review
tzssangglass Sep 18, 2021
be61095
fix code review
tzssangglass Sep 18, 2021
46f19be
resolve code review
tzssangglass Sep 21, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
48 changes: 43 additions & 5 deletions apisix/debug.lua
Expand Up @@ -17,9 +17,8 @@
local require = require
local yaml = require("tinyyaml")
local log = require("apisix.core.log")
local json = require("apisix.core.json")
local profile = require("apisix.core.profile")
local process = require("ngx.process")
local request = require("apisix.core.request")
local lfs = require("lfs")
local io = io
local ngx = ngx
Expand All @@ -30,6 +29,7 @@ local setmetatable = setmetatable
local pcall = pcall
local ipairs = ipairs
local unpack = unpack
local inspect = require "inspect"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to put all require together, and in the form require("ngx.process")

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

require("apisix.debug") in init.lua --> require("ngx.process") in debug.lua, will result in error as process.lua:5: unsupported subsystem: stream, see: https://github.com/apache/apisix/runs/3578221555

ngx.process API for stream subsystem is not implemented on openresty 1.19.3.2(but is implemented on 1.19.9.1), so I move require("ngx.process") to function.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I mean to use require("inspect"), the require("ngx.process") is just an example.

local debug_yaml_path = profile:yaml_path("debug")
local debug_yaml
local debug_yaml_ctime
Expand Down Expand Up @@ -126,13 +126,13 @@ local function apple_new_fun(module, fun_name, file_path, hook_conf)
local arg = {...}
if hook_conf.is_print_input_args then
log[log_level]("call require(\"", file_path, "\").", fun_name,
"() args:", json.delay_encode(arg, true))
"() args:", inspect(arg))
end

local ret = {self.fun_org(...)}
if hook_conf.is_print_return_value then
log[log_level]("call require(\"", file_path, "\").", fun_name,
"() return:", json.delay_encode(ret, true))
"() return:", inspect(ret))
end
return unpack(ret)
end
Expand All @@ -148,7 +148,9 @@ end

function sync_debug_hooks()
if not debug_yaml_ctime or debug_yaml_ctime == pre_mtime then
return
if not (debug_yaml and debug_yaml.http and debug_yaml.http.dynamic) then
return
end
end

for _, hook in pairs(enabled_hooks) do
Expand Down Expand Up @@ -200,7 +202,43 @@ local function sync_debug_status(premature)
end


local function check()
if not debug_yaml or not debug_yaml.http then
return false
end

local http = debug_yaml.http
if not http or not http.enable_header_name or not http.dynamic then
return false
end

return true
end

function _M.dynamic_enable(api_ctx)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is called in the request level, but it changes a field at the module level. Look like it will affect other requests?

if not check() then
return
end

if request.header(api_ctx, debug_yaml.http.enable_header_name) then
debug_yaml.hook_conf.enable = true
sync_debug_hooks()
end
end


function _M.dynamic_disable()
if not check() then
return
end

debug_yaml.hook_conf.enable = false
sync_debug_hooks()
end


function _M.init_worker()
local process = require("ngx.process")
if process.type() ~= "worker" then
return
end
Expand Down
5 changes: 5 additions & 0 deletions apisix/init.lua
Expand Up @@ -30,6 +30,7 @@ local upstream_util = require("apisix.utils.upstream")
local ctxdump = require("resty.ctxdump")
local ipmatcher = require("resty.ipmatcher")
local ngx_balancer = require("ngx.balancer")
local debug = require("apisix.debug")
local ngx = ngx
local get_method = ngx.req.get_method
local ngx_exit = ngx.exit
Expand Down Expand Up @@ -353,6 +354,8 @@ function _M.http_access_phase()

core.ctx.set_vars_meta(api_ctx)

debug.dynamic_enable(api_ctx)

local uri = api_ctx.var.uri
if local_conf.apisix and local_conf.apisix.delete_uri_tail_slash then
if str_byte(uri, #uri) == str_byte("/") then
Expand Down Expand Up @@ -704,6 +707,8 @@ function _M.http_log_phase()
core.tablepool.release("matched_route_record", api_ctx.curr_req_matched)
end

debug.dynamic_disable()

core.tablepool.release("api_ctx", api_ctx)
end

Expand Down
3 changes: 3 additions & 0 deletions conf/debug.yaml
Expand Up @@ -14,6 +14,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
http:
dynamic: false # enable or disable this feature
tzssangglass marked this conversation as resolved.
Show resolved Hide resolved
enable_header_name: X-APISIX-Dynamic-Debug # the header name of dynamic enable
hook_conf:
enable: false # enable or disable this feature
name: hook_phase # the name of module and function list
Expand Down
22 changes: 22 additions & 0 deletions docs/en/latest/architecture-design/debug-mode.md
Expand Up @@ -76,3 +76,25 @@ hook_phase: # Module Function List, Name: hook_phase
- http_log_phase
#END
```

### Dynamic Advanced Debug Mode
tzssangglass marked this conversation as resolved.
Show resolved Hide resolved

Dynamic advanced debug mode is based on advanced debug mode, which can be enabled dynamically by a single request and turned off automatically when the request ends.
tzssangglass marked this conversation as resolved.
Show resolved Hide resolved

Example:

```yaml
http:
dynamic: true # 是否动态开启高级调试模式
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need English comment in English doc

enable_header_name: X-APISIX-Dynamic-Debug # 对携带此 header 的请求开启高级调试模式
......
#END
```

Dynamically enable advanced debugging mode, example:
tzssangglass marked this conversation as resolved.
Show resolved Hide resolved

```shell
curl 127.0.0.1:9090/hello --header 'X-APISIX-Dynamic-Debug: foo'
```

Notice: Dynamic advanced debug mode cannot debug the `apisix.http_access_phase` module (because the request enters the `apisix.http_access_phase` module before it determines whether advanced debug mode is dynamically enabled).
tzssangglass marked this conversation as resolved.
Show resolved Hide resolved
22 changes: 22 additions & 0 deletions docs/zh/latest/architecture-design/debug-mode.md
Expand Up @@ -78,3 +78,25 @@ hook_phase: # 模块函数列表,名字:hook_phase
- http_log_phase
#END
```

### 动态高级调试模式

动态高级调试模式是基于高级调试模式,可以由单个请求动态开启高级调试模式,请求结束后自动关闭。设置 `conf/debug.yaml` 中的选项。
tzssangglass marked this conversation as resolved.
Show resolved Hide resolved

示例:

```yaml
http:
dynamic: true # 是否动态开启高级调试模式
enable_header_name: X-APISIX-Dynamic-Debug # 对携带此 header 的请求开启高级调试模式
......
#END
```

动态开启高级调试模式,示例:

```shell
curl 127.0.0.1:9090/hello --header 'X-APISIX-Dynamic-Debug: foo'
```

注意:动态高级调试模式无法调试 `apisix.http_access_phase` 模块(因为请求进入 `apisix.http_access_phase` 模块后,才会判断是否动态开启高级调试模式)。
1 change: 1 addition & 0 deletions rockspec/apisix-master-0.rockspec
Expand Up @@ -69,6 +69,7 @@ dependencies = {
"ext-plugin-proto = 0.3.0",
"casbin = 1.26.0",
"api7-snowflake = 2.0-1",
"inspect == 3.1.1",
}

build = {
Expand Down