This is an automated email from the ASF dual-hosted git repository.
monkeydluffy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git
The following commit(s) were added to refs/heads/master by this push:
new 94fc89488 feat: file-logger add vars (#9712)
94fc89488 is described below
commit 94fc894889d75422ee9b64f91ec3369158d19648
Author: kamly <[email protected]>
AuthorDate: Thu Jul 13 11:18:27 2023 +0800
feat: file-logger add vars (#9712)
---
apisix/plugins/file-logger.lua | 17 +++++++
apisix/utils/log-util.lua | 20 ++++++++
docs/en/latest/plugins/file-logger.md | 41 ++++++++++++++++
docs/zh/latest/plugins/file-logger.md | 41 ++++++++++++++++
t/plugin/file-logger2.t | 92 +++++++++++++++++++++++++++++++++++
5 files changed, 211 insertions(+)
diff --git a/apisix/plugins/file-logger.lua b/apisix/plugins/file-logger.lua
index 97140abfa..d07c49270 100644
--- a/apisix/plugins/file-logger.lua
+++ b/apisix/plugins/file-logger.lua
@@ -16,6 +16,7 @@
--
local log_util = require("apisix.utils.log-util")
local core = require("apisix.core")
+local expr = require("resty.expr.v1")
local ngx = ngx
local io_open = io.open
local is_apisix_or, process = pcall(require, "resty.apisix.process")
@@ -38,6 +39,13 @@ local schema = {
items = {
type = "array"
}
+ },
+ match = {
+ type = "array",
+ maxItems = 20,
+ items = {
+ type = "array",
+ },
}
},
required = {"path"}
@@ -65,6 +73,12 @@ function _M.check_schema(conf, schema_type)
if schema_type == core.schema.TYPE_METADATA then
return core.schema.check(metadata_schema, conf)
end
+ if conf.match then
+ local ok, err = expr.new(conf.match)
+ if not ok then
+ return nil, "failed to validate the 'match' expression: " .. err
+ end
+ end
return core.schema.check(schema, conf)
end
@@ -150,6 +164,9 @@ end
function _M.log(conf, ctx)
local entry = log_util.get_log_entry(plugin_name, conf, ctx)
+ if entry == nil then
+ return
+ end
write_file_data(conf, entry)
end
diff --git a/apisix/utils/log-util.lua b/apisix/utils/log-util.lua
index 4aecf290e..8e9cb9c01 100644
--- a/apisix/utils/log-util.lua
+++ b/apisix/utils/log-util.lua
@@ -210,7 +210,27 @@ function _M.inject_get_full_log(f)
end
+local function is_match(match, ctx)
+ local match_result
+ for _, m in pairs(match) do
+ local expr, _ = expr.new(m)
+ match_result = expr:eval(ctx.var)
+ if match_result then
+ break
+ end
+ end
+
+ return match_result
+end
+
+
function _M.get_log_entry(plugin_name, conf, ctx)
+ -- If the "match" configuration is set and the matching conditions are not
met,
+ -- then do not log the message.
+ if conf.match and not is_match(conf.match, ctx) then
+ return
+ end
+
local metadata = plugin.plugin_metadata(plugin_name)
core.log.info("metadata: ", core.json.delay_encode(metadata))
diff --git a/docs/en/latest/plugins/file-logger.md
b/docs/en/latest/plugins/file-logger.md
index 9260cf72a..776cb6c81 100644
--- a/docs/en/latest/plugins/file-logger.md
+++ b/docs/en/latest/plugins/file-logger.md
@@ -49,6 +49,7 @@ The `file-logger` Plugin is used to push log streams to a
specific location.
| log_format | object | False | Log format declared as key value pairs in
JSON format. Values only support strings. [APISIX](../apisix-variable.md) or
[Nginx](http://nginx.org/en/docs/varindex.html) variables can be used by
prefixing the string with `$`. |
| include_resp_body | boolean | False | When set to `true` includes
the response body in the log file.
|
| include_resp_body_expr | array | False | When the `include_resp_body`
attribute is set to `true`, use this to filter based on
[lua-resty-expr](https://github.com/api7/lua-resty-expr). If present, only logs
the response into file if the expression evaluates to `true`. |
+| match | array[] | False | Logs will be recorded when the rule
matching is successful if the option is set. See
[lua-resty-expr](https://github.com/api7/lua-resty-expr#operator-list) for a
list of available expressions. |
## Metadata
@@ -110,6 +111,46 @@ curl -i http://127.0.0.1:9080/hello
You will be able to find the `file.log` file in the configured `logs`
directory.
+## Filter logs
+
+```shell
+curl http://127.0.0.1:9180/apisix/admin/routes/1 \
+-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
+{
+ "plugins": {
+ "file-logger": {
+ "path": "logs/file.log",
+ "match": {
+ {
+ { "arg_name","==","jack" }
+ }
+ }
+ }
+ },
+ "upstream": {
+ "type": "roundrobin",
+ "nodes": {
+ "127.0.0.1:9001": 1
+ }
+ },
+ "uri": "/hello"
+}'
+```
+
+Test:
+
+```shell
+curl -i http://127.0.0.1:9080/hello?name=jack
+```
+
+Log records can be seen in `logs/file.log`.
+
+```shell
+curl -i http://127.0.0.1:9080/hello?name=rose
+```
+
+Log records cannot be seen in `logs/file.log`.
+
## Disable Plugin
To disable the `file-logger` Plugin, you can delete the corresponding JSON
configuration from the Plugin configuration. APISIX will automatically reload
and you do not have to restart for this to take effect.
diff --git a/docs/zh/latest/plugins/file-logger.md
b/docs/zh/latest/plugins/file-logger.md
index 34f3dcd72..607d222ba 100644
--- a/docs/zh/latest/plugins/file-logger.md
+++ b/docs/zh/latest/plugins/file-logger.md
@@ -51,6 +51,7 @@ description: API 网关 Apache APISIX file-logger 插件可用于将日志数据
| log_format | object | 否 | 以 JSON 格式的键值对来声明日志格式。对于值部分,仅支持字符串。如果是以
`$` 开头,则表明是要获取 [APISIX 变量](../apisix-variable.md) 或 [NGINX
内置变量](http://nginx.org/en/docs/varindex.html)。 |
| include_resp_body | boolean | 否 | 当设置为 `true` 时,生成的文件包含响应体。
|
| include_resp_body_expr | array | 否 | 当 `include_resp_body` 属性设置为
`true` 时,使用该属性并基于 [lua-resty-expr](https://github.com/api7/lua-resty-expr)
进行过滤。如果存在,则仅在表达式计算结果为 `true` 时记录响应。 |
+| match | array[] | 否 | 当设置了这个选项后,只有匹配规则的日志才会被记录。`match`
是一个表达式列表,具体请参考
[lua-resty-expr](https://github.com/api7/lua-resty-expr#operator-list)。 |
## 插件元数据设置
@@ -124,6 +125,46 @@ hello, world
访问成功后,你可以在对应的 `logs` 目录下找到 `file.log` 文件。
+## 过滤日志
+
+```shell
+curl http://127.0.0.1:9180/apisix/admin/routes/1 \
+-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
+{
+ "plugins": {
+ "file-logger": {
+ "path": "logs/file.log",
+ "match": {
+ {
+ { "arg_name","==","jack" }
+ }
+ }
+ }
+ },
+ "upstream": {
+ "type": "roundrobin",
+ "nodes": {
+ "127.0.0.1:9001": 1
+ }
+ },
+ "uri": "/hello"
+}'
+```
+
+测试:
+
+```shell
+curl -i http://127.0.0.1:9080/hello?name=jack
+```
+
+在 `logs/file.log` 中可以看到日志记录
+
+```shell
+curl -i http://127.0.0.1:9080/hello?name=rose
+```
+
+在 `logs/file.log` 中看不到日志记录
+
## 禁用插件
当你需要禁用该插件时,可以通过如下命令删除相应的 JSON 配置,APISIX 将会自动重新加载相关配置,无需重启服务:
diff --git a/t/plugin/file-logger2.t b/t/plugin/file-logger2.t
index 90ce001c6..5cf3a76cc 100644
--- a/t/plugin/file-logger2.t
+++ b/t/plugin/file-logger2.t
@@ -274,3 +274,95 @@ passed
}
--- response_body
write file log success
+
+
+
+=== TEST 8: Add new configuration with match
+--- 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,
+ [[{
+ "plugins": {
+ "file-logger": {
+ "path": "file-with-match.log",
+ "match": [
+ [
+ [ "arg_name","==","jack" ]
+ ]
+ ],
+ "log_format": {
+ "request": "$request"
+ }
+ }
+ },
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:1982": 1
+ },
+ "type": "roundrobin"
+ },
+ "uri": "/hello"
+ }]]
+ )
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- response_body
+passed
+
+
+
+=== TEST 9: Request match
+--- config
+ location /t {
+ content_by_lua_block {
+ local core = require("apisix.core")
+ local t = require("lib.test_admin").test
+ local code = t("/hello?name=jack", ngx.HTTP_GET)
+ local fd, err = io.open("file-with-match.log", 'r')
+ if not fd then
+ core.log.error("failed to open file: file-with-match.log,
error info: ", err)
+ return
+ end
+ local msg = fd:read()
+
+ local new_msg = core.json.decode(msg)
+ if new_msg.request == 'GET /hello?name=jack HTTP/1.1'
+ and new_msg.route_id == '1'
+ then
+ msg = "write file log success"
+ ngx.status = code
+ ngx.say(msg)
+ end
+
+ os.remove("file-with-match.log")
+ }
+ }
+--- response_body
+write file log success
+
+
+
+=== TEST 10: Request not match
+--- config
+ location /t {
+ content_by_lua_block {
+ local core = require("apisix.core")
+ local t = require("lib.test_admin").test
+ local code = t("/hello?name=tony", ngx.HTTP_GET)
+ local fd, err = io.open("file-with-match.log", 'r')
+ if not fd then
+ local msg = "not write file log"
+ ngx.say(msg)
+ return
+ end
+ }
+ }
+--- response_body
+not write file log