diff --git a/conf/config.yaml b/conf/config.yaml index c860d9347b12..9864584a2dc4 100644 --- a/conf/config.yaml +++ b/conf/config.yaml @@ -3,6 +3,7 @@ apisix: node_ssl_listen: 9443 enable_heartbeat: true enable_admin: true + enable_debug: false allow_admin: "127.0.0.0/24" real_ip_header: "X-Real-IP" # http://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header real_ip_from: # http://nginx.org/en/docs/http/ngx_http_realip_module.html#set_real_ip_from diff --git a/doc/architecture-design-cn.md b/doc/architecture-design-cn.md index 5c05492d2648..c4b8e8a93ece 100644 --- a/doc/architecture-design-cn.md +++ b/doc/architecture-design-cn.md @@ -6,6 +6,7 @@ - [**Consumer**](#consumer) - [**Plugin**](#plugin) - [**Upstream**](#upstream) +- [**Debug mode**](#Debug-mode) ## apisix @@ -322,3 +323,28 @@ curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d ' 更多细节可以参考[健康检查的文档](health-check.md). [返回目录](#目录) + + +## Debug mode + +开启调试模式后,会在请求应答时,输出更多的内部信息,比如加载了哪些插件等。 + +设置 `conf/config.yaml` 中的 `apisix.enable_debug` 为 `true`,即可开启调试模式。 + +比如对 `/hello` 开启了 `limit-conn`和`limit-count`插件,这时候应答头中会有 `Apisix-Plugins: limit-conn, limit-count` 出现。 + +```shell +$ curl http://127.0.0.1:1984/hello -i +HTTP/1.1 200 OK +Content-Type: text/plain +Transfer-Encoding: chunked +Connection: keep-alive +Apisix-Plugins: limit-conn, limit-count +X-RateLimit-Limit: 2 +X-RateLimit-Remaining: 1 +Server: openresty + +hello world +``` + +[返回目录](#目录) diff --git a/lua/apisix/core/config_etcd.lua b/lua/apisix/core/config_etcd.lua index 4cb8856b1abc..51ded460cba6 100644 --- a/lua/apisix/core/config_etcd.lua +++ b/lua/apisix/core/config_etcd.lua @@ -1,6 +1,6 @@ -- Copyright (C) Yuansheng Wang -local fetch_local_conf = require("apisix.core.config_local").local_conf +local config_local = require("apisix.core.config_local") local log = require("apisix.core.log") local json = require("apisix.core.json") local etcd = require("resty.etcd") @@ -22,9 +22,11 @@ local pcall = pcall local _M = { - version = 0.1, - local_conf = fetch_local_conf, + version = 0.2, + local_conf = config_local.local_conf, + clear_local_cache = config_local.clear_cache, } + local mt = { __index = _M, __tostring = function(self) @@ -300,7 +302,7 @@ end function _M.new(key, opts) - local local_conf, err = fetch_local_conf() + local local_conf, err = config_local.local_conf() if not local_conf then return nil, err end diff --git a/lua/apisix/core/config_local.lua b/lua/apisix/core/config_local.lua index 265201129e1f..fe3d434f43e9 100644 --- a/lua/apisix/core/config_local.lua +++ b/lua/apisix/core/config_local.lua @@ -6,9 +6,12 @@ local ngx = ngx local io_open = io.open local type = type local local_conf_path = ngx.config.prefix() .. "conf/config.yaml" +local config_data -local _M = {version = 0.1} +local _M = { + version = 0.2, +} local function read_file(path) @@ -23,14 +26,23 @@ local function read_file(path) return content end +function _M.clear_cache() + config_data = nil +end + + +function _M.local_conf(force) + if not force and config_data then + return config_data + end -function _M.local_conf() local yaml_config, err = read_file(local_conf_path) if type(yaml_config) ~= "string" then return nil, "failed to read config file:" .. err end - return yaml.parse(yaml_config) + config_data = yaml.parse(yaml_config) + return config_data end diff --git a/lua/apisix/plugin.lua b/lua/apisix/plugin.lua index de62b695532d..7b3ddc63d404 100644 --- a/lua/apisix/plugin.lua +++ b/lua/apisix/plugin.lua @@ -8,10 +8,11 @@ local pairs = pairs local type = type local local_plugins = core.table.new(10, 0) local local_plugins_hash = core.table.new(10, 0) +local local_conf local _M = { - version = 0.1, + version = 0.2, load_times = 0, plugins = local_plugins, plugins_hash = local_plugins_hash, @@ -19,7 +20,7 @@ local _M = { local function sort_plugin(l, r) - return l.priority >= r.priority + return l.priority > r.priority end @@ -59,7 +60,7 @@ local function load() core.table.clear(local_plugins) core.table.clear(local_plugins_hash) - local local_conf = core.config.local_conf() + local_conf = core.config.local_conf(true) local plugin_names = local_conf.plugins if not plugin_names then return nil, "failed to read plugin list form local file" @@ -82,8 +83,14 @@ local function load() sort_tab(local_plugins, sort_plugin) end - for _, plugin in ipairs(local_plugins) do + for i, plugin in ipairs(local_plugins) do local_plugins_hash[plugin.name] = plugin + if local_conf and local_conf.apisix + and local_conf.apisix.enable_debug then + core.log.warn("loaded plugin and sort by priority:", + " ", plugin.priority, + " name: ", plugin.name) + end end _M.load_times = _M.load_times + 1 @@ -136,6 +143,9 @@ function _M.filter(user_route, plugins) plugins = plugins or core.table.new(#local_plugins * 2, 0) local user_plugin_conf = user_route.value.plugins if user_plugin_conf == nil then + if local_conf and local_conf.apisix.enable_debug then + core.response.set_header("Apisix-Plugins", "no plugin") + end return plugins end @@ -149,6 +159,14 @@ function _M.filter(user_route, plugins) end end + if local_conf.apisix.enable_debug then + local t = {} + for i = 1, #plugins, 2 do + core.table.insert(t, plugins[i].name) + end + core.response.set_header("Apisix-Plugins", core.table.concat(t, ", ")) + end + return plugins end diff --git a/lua/apisix/plugins/example-plugin.lua b/lua/apisix/plugins/example-plugin.lua index e8ae9eca1193..75871bbe0d9a 100644 --- a/lua/apisix/plugins/example-plugin.lua +++ b/lua/apisix/plugins/example-plugin.lua @@ -21,7 +21,7 @@ local plugin_name = "example-plugin" local _M = { version = 0.1, - priority = 1000, -- TODO: add a type field, may be a good idea + priority = 0, -- TODO: add a type field, may be a good idea name = plugin_name, schema = schema, } diff --git a/lua/apisix/plugins/heartbeat.lua b/lua/apisix/plugins/heartbeat.lua index 370b8e0de045..7e1fdf84213e 100644 --- a/lua/apisix/plugins/heartbeat.lua +++ b/lua/apisix/plugins/heartbeat.lua @@ -11,7 +11,7 @@ local apisix_heartbeat_addr = "https://iresty.com/apisix/heartbeat?" local _M = { version = 0.1, - priority = 1000, + priority = 100, name = plugin_name, } diff --git a/t/debug-mode.t b/t/debug-mode.t new file mode 100644 index 000000000000..3f56ff63a897 --- /dev/null +++ b/t/debug-mode.t @@ -0,0 +1,159 @@ +use t::APISix 'no_plan'; + +repeat_each(1); +no_long_string(); +no_root_location(); + +sub read_file($) { + my $infile = shift; + open my $in, $infile + or die "cannot open $infile for reading: $!"; + my $cert = do { local $/; <$in> }; + close $in; + $cert; +} + +our $yaml_config = read_file("conf/config.yaml"); +$yaml_config =~ s/node_listen: 9080/node_listen: 1984/; +$yaml_config =~ s/enable_heartbeat: true/enable_heartbeat: false/; +$yaml_config =~ s/enable_debug: false/enable_debug: true/; + + +run_tests; + +__DATA__ + +=== TEST 1: loaded plugin +--- config + location /t { + content_by_lua_block { + ngx.sleep(0.3) + ngx.say("done") + } + } +--- yaml_config eval: $::yaml_config +--- request +GET /t +--- response_body +done +--- grep_error_log eval +qr/loaded plugin and sort by priority: [-\d]+ name: [\w-]+/ +--- grep_error_log_out +loaded plugin and sort by priority: 2510 name: jwt-auth +loaded plugin and sort by priority: 2500 name: key-auth +loaded plugin and sort by priority: 1003 name: limit-conn +loaded plugin and sort by priority: 1002 name: limit-count +loaded plugin and sort by priority: 1001 name: limit-req +loaded plugin and sort by priority: 1000 name: node-status +loaded plugin and sort by priority: 500 name: prometheus +loaded plugin and sort by priority: 0 name: example-plugin +loaded plugin and sort by priority: -1000 name: zipkin + + + +=== TEST 2: set route(no plugin) +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "methods": ["GET"], + "uri": "/hello", + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + } + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed +--- no_error_log +[error] + + + +=== TEST 3: hit routes +--- request +GET /hello +--- yaml_config eval: $::yaml_config +--- response_body +hello world +--- response_headers +Apisix-Plugins: no plugin +--- no_error_log +[error] + + + +=== TEST 4: set route(one plugin) +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "methods": ["GET"], + "plugins": { + "limit-count": { + "count": 2, + "time_window": 60, + "rejected_code": 503, + "key": "remote_addr" + }, + "limit-conn": { + "conn": 100, + "burst": 50, + "default_conn_delay": 0.1, + "rejected_code": 503, + "key": "remote_addr" + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/hello" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed +--- no_error_log +[error] + + + +=== TEST 5: hit routes +--- request +GET /hello +--- yaml_config eval: $::yaml_config +--- response_body +hello world +--- response_headers +Apisix-Plugins: limit-conn, limit-count +--- no_error_log +[error] diff --git a/t/plugin/example.t b/t/plugin/example.t index da35174b5d85..69cff74f13e3 100644 --- a/t/plugin/example.t +++ b/t/plugin/example.t @@ -145,7 +145,7 @@ done --- request GET /t --- response_body -plugin name: example-plugin priority: 1000 +plugin name: example-plugin priority: 0 --- yaml_config etcd: host: "http://127.0.0.1:2379" # etcd address