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

Reply via email to