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 24 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 50 additions & 5 deletions apisix/debug.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,19 @@
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 lfs = require("lfs")
local io = io
local ngx = ngx
local re_find = ngx.re.find
local get_headers = ngx.req.get_headers
local type = type
local pairs = pairs
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 @@ -123,15 +124,35 @@ local function apple_new_fun(module, fun_name, file_path, hook_conf)

function mt.__call(self, ...)
local arg = {...}
local http_filter = debug_yaml.http_filter
local api_ctx = ngx.ctx.api_ctx
local enable_by_hook = not (http_filter and http_filter.enable)
or (api_ctx and api_ctx.enable_dynamic_debug)
tzssangglass marked this conversation as resolved.
Show resolved Hide resolved
local enable_by_header_filter = (http_filter and http_filter.enable)
and (api_ctx and api_ctx.enable_dynamic_debug)
if hook_conf.is_print_input_args then
log[log_level]("call require(\"", file_path, "\").", fun_name,
"() args:", json.delay_encode(arg, true))
if enable_by_hook then
tzssangglass marked this conversation as resolved.
Show resolved Hide resolved
log[log_level]("call require(\"", file_path, "\").", fun_name,
"() args:", inspect(arg))
end

if enable_by_header_filter then
log[log_level]("call require(\"", file_path, "\").", fun_name,
"() args:", inspect(arg))
end
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))
if enable_by_hook then
log[log_level]("call require(\"", file_path, "\").", fun_name,
"() return:", inspect(ret))
end

if enable_by_header_filter then
log[log_level]("call require(\"", file_path, "\").", fun_name,
"() return:", inspect(ret))
end
end
return unpack(ret)
end
Expand Down Expand Up @@ -199,6 +220,30 @@ local function sync_debug_status(premature)
end


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

local http_filter = debug_yaml.http_filter
if not http_filter or not http_filter.enable_header_name or not http_filter.enable then
return false
end

return true
end

function _M.dynamic_debug(api_ctx)
if not check() then
return
end

if get_headers()[debug_yaml.http_filter.enable_header_name] then
api_ctx.enable_dynamic_debug = true
end
end


function _M.enable_debug()
if not debug_yaml or not debug_yaml.basic then
return false
Expand Down
3 changes: 3 additions & 0 deletions apisix/init.lua
Original file line number Diff line number Diff line change
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 @@ -355,6 +356,8 @@ function _M.http_access_phase()

core.ctx.set_vars_meta(api_ctx)

debug.dynamic_debug(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
3 changes: 3 additions & 0 deletions conf/debug.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
#
basic:
enable: false
http_filter:
enable: false # enable or disable this feature
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
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,25 @@ hook_phase: # Module Function List, Name: hook_phase
- http_log_phase
#END
```

### Enable Advanced Debug Mode Dynamically

The advanced debug mode can take effect in particular requests by dynamic rule.

Example:

```yaml
http_filter:
enable: true # Enable/Disable Advanced Debug Mode Dynamically
enable_header_name: X-APISIX-Dynamic-Debug # Trace for the request with this header
......
#END
```

Dynamically enable advanced debugging mode in a particular request like this:

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

Notice: We can not only hook the `apisix.http_access_phase` module in particular requests. 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
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,25 @@ hook_phase: # 模块函数列表,名字:hook_phase
- http_log_phase
#END
```

### 动态高级调试模式

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

示例:

```yaml
http_filter:
enable: 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
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ dependencies = {
"ext-plugin-proto = 0.3.0",
"casbin = 1.26.0",
"api7-snowflake = 2.0-1",
"inspect == 3.1.1",
}

build = {
Expand Down
Loading