You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by me...@apache.org on 2020/12/17 14:26:32 UTC

[apisix] branch master updated: feat: support ctx.var to get service_name and route_name (#3036)

This is an automated email from the ASF dual-hosted git repository.

membphis 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 bdd00e1  feat: support ctx.var to get service_name and route_name (#3036)
bdd00e1 is described below

commit bdd00e1f55fd13cd3d2b12656ec1dc2d4e3f6e0b
Author: Yuelin Zheng <52...@users.noreply.github.com>
AuthorDate: Thu Dec 17 22:26:25 2020 +0800

    feat: support ctx.var to get service_name and route_name (#3036)
    
    close #2982
---
 apisix/core/ctx.lua              |   6 +
 apisix/init.lua                  |   2 +
 doc/plugins/http-logger.md       |  12 +-
 doc/zh-cn/plugins/http-logger.md |  12 +-
 t/core/ctx.t                     | 321 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 351 insertions(+), 2 deletions(-)

diff --git a/apisix/core/ctx.lua b/apisix/core/ctx.lua
index 4451c4b..962a270 100644
--- a/apisix/core/ctx.lua
+++ b/apisix/core/ctx.lua
@@ -174,6 +174,12 @@ do
             elseif key == "consumer_name" then
                 val = ngx.ctx.api_ctx and ngx.ctx.api_ctx.consumer_name
 
+            elseif key == "route_name" then
+                val = ngx.ctx.api_ctx and ngx.ctx.api_ctx.route_name
+
+            elseif key == "service_name" then
+                val = ngx.ctx.api_ctx and ngx.ctx.api_ctx.service_name
+
             else
                 val = get_var(key, t._request)
             end
diff --git a/apisix/init.lua b/apisix/init.lua
index 5a4b075..1b9c62c 100644
--- a/apisix/init.lua
+++ b/apisix/init.lua
@@ -413,6 +413,7 @@ function _M.http_access_phase()
         api_ctx.conf_version = route.modifiedIndex .. "&" .. service.modifiedIndex
         api_ctx.conf_id = route.value.id .. "&" .. service.value.id
         api_ctx.service_id = service.value.id
+        api_ctx.service_name = service.value.name
 
         if enable_websocket == nil then
             enable_websocket = service.value.enable_websocket
@@ -424,6 +425,7 @@ function _M.http_access_phase()
         api_ctx.conf_id = route.value.id
     end
     api_ctx.route_id = route.value.id
+    api_ctx.route_name = route.value.name
 
     local up_id = route.value.upstream_id
     if up_id then
diff --git a/doc/plugins/http-logger.md b/doc/plugins/http-logger.md
index 3129c79..01e3888 100644
--- a/doc/plugins/http-logger.md
+++ b/doc/plugins/http-logger.md
@@ -87,10 +87,20 @@ hello, world
 
 | Name             | Type    | Requirement | Default       | Valid   | Description                                                                              |
 | ---------------- | ------- | ----------- | ------------- | ------- | ---------------------------------------------------------------------------------------- |
-| log_format       | object  | optional    | {"host": "$host", "@timestamp": "$time_iso8601", "client_ip": "$remote_addr"} |         | Log format declared as JSON object. Only string is supported in the `value` part. If the value starts with `$`, the value is [Nginx variable](http://nginx.org/en/docs/varindex.html). |
+| log_format       | object  | optional    | {"host": "$host", "@timestamp": "$time_iso8601", "client_ip": "$remote_addr"} |         | Log format declared as JSON object. Only string is supported in the `value` part. If the value starts with `$`, it means to get `APISIX` variables or [Nginx variable](http://nginx.org/en/docs/varindex.html). |
 
  Note that the metadata configuration is applied in global scope, which means it will take effect on all Route or Service which use http-logger plugin.
 
+**APISIX Variables**
+
+|   Variable Name  |      Description        | Usage Example  |
+|------------------|-------------------------|----------------|
+| route_id         | id of `route`          | $route_id      |
+| route_name       | name of `route`        | $route_name    |
+| service_id       | id of `service`        | $service_id    |
+| service_name     | name of `service`      | $service_name  |
+| consumer_name    | username of `consumer` | $consumer_name |
+
 ### Example
 
 ```shell
diff --git a/doc/zh-cn/plugins/http-logger.md b/doc/zh-cn/plugins/http-logger.md
index 832465f..b25545f 100644
--- a/doc/zh-cn/plugins/http-logger.md
+++ b/doc/zh-cn/plugins/http-logger.md
@@ -87,7 +87,17 @@ hello, world
 
 | 名称             | 类型    | 必选项 | 默认值        | 有效值  | 描述                                             |
 | ---------------- | ------- | ------ | ------------- | ------- | ------------------------------------------------ |
-| log_format       | object  | 可选   | {"host": "$host", "@timestamp": "$time_iso8601", "client_ip": "$remote_addr"} |         | 以 Hash 对象方式声明日志格式。对 value 部分,仅支持字符串。如果是以`$`开头,则表明是要获取 [Nginx 内置变量](http://nginx.org/en/docs/varindex.html)。特别的,该设置是全局生效的,意味着指定 log_format 后,将对所有绑定 http-logger 的 Route 或 Service 生效。 |
+| log_format       | object  | 可选   | {"host": "$host", "@timestamp": "$time_iso8601", "client_ip": "$remote_addr"} |         | 以 JSON 对象方式声明日志格式。对 value 部分,仅支持字符串。如果是以 `$` 开头,则表明是要获取 __APISIX__ 变量或 [Nginx 内置变量](http://nginx.org/en/docs/varindex.html)。特别的,该设置是全局生效的,意味着指定 log_format 后,将对所有绑定 http-logger 的 Route 或 Service 生效。 |
+
+**APISIX 变量**
+
+|       变量名      |           描述          |      使用示例    |
+|------------------|-------------------------|----------------|
+| route_id         | `route` 的 id           | $route_id      |
+| route_name       | `route` 的 name         | $route_name    |
+| service_id       | `service` 的 id         | $service_id    |
+| service_name     | `service` 的 name       | $service_name  |
+| consumer_name    | `consumer` 的 username  | $consumer_name |
 
 ### 设置日志格式示例
 
diff --git a/t/core/ctx.t b/t/core/ctx.t
index a69cb13..482f93e 100644
--- a/t/core/ctx.t
+++ b/t/core/ctx.t
@@ -588,3 +588,324 @@ hello world
 consumer_name: consumer_name is nil
 --- no_error_log
 [error]
+
+
+
+=== TEST 23: add plugin metadata `service_name`
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/plugin_metadata/http-logger',
+                ngx.HTTP_PUT,
+                [[{
+                    "log_format": {
+                        "service_name": "$service_name"
+                    }
+                }]],
+                [[{
+                    "node": {
+                        "value": {
+                            "log_format": {
+                                "service_name": "$service_name"
+                            }
+                        }
+                    },
+                    "action": "set"
+                }]]
+                )
+
+            ngx.status = code
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 24: add `http-logger` plugin on service
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/services/1',
+                 ngx.HTTP_PUT,
+                 [[{
+                    "name": "ctx_var-support-service_name",
+                    "plugins": {
+                        "http-logger": {
+                            "uri": "http://127.0.0.1:1980/log",
+                            "batch_max_size": 1,
+                            "max_retry_count": 1,
+                            "retry_delay": 2,
+                            "buffer_duration": 2,
+                            "concat_method": "json"
+                        }
+                    },
+                    "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 25: route binding service and concat_method is json
+--- 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,
+                 [[{
+                    "service_id": 1,
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:1982": 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 26: hit route and report http logger
+--- request
+GET /hello
+--- response_body
+hello world
+--- error_log eval
+qr/request log: \{"route_id":"1","service_id":"1","service_name":"ctx_var-support-service_name"\}/
+
+
+
+=== TEST 27: log_format is configured with `service_name`, but there is no matching service
+--- 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": {
+                        "http-logger": {
+                            "uri": "http://127.0.0.1:1980/log",
+                            "batch_max_size": 1,
+                            "max_retry_count": 1,
+                            "retry_delay": 2,
+                            "buffer_duration": 2,
+                            "concat_method": "json"
+                        }
+                    },
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:1982": 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 28: hit route but there is no matching service
+--- request
+GET /hello
+--- response_body
+hello world
+--- error_log eval
+qr/request log: \{"route_id":"1"\}/
+
+
+
+=== TEST 29: add plugin metadata `route_name`
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/plugin_metadata/http-logger',
+                ngx.HTTP_PUT,
+                [[{
+                    "log_format": {
+                        "route_name": "$route_name"
+                    }
+                }]],
+                [[{
+                    "node": {
+                        "value": {
+                            "log_format": {
+                                "route_name": "$route_name"
+                            }
+                        }
+                    },
+                    "action": "set"
+                }]]
+                )
+
+            ngx.status = code
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 30: sanity, batch_max_size=1 and concat_method is json
+--- 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,
+                 [[{
+                    "name": "ctx_var-support-route_name",
+                    "plugins": {
+                        "http-logger": {
+                            "uri": "http://127.0.0.1:1980/log",
+                            "batch_max_size": 1,
+                            "max_retry_count": 1,
+                            "retry_delay": 2,
+                            "buffer_duration": 2,
+                            "concat_method": "json"
+                        }
+                    },
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:1982": 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 31: hit route and report http logger
+--- request
+GET /hello
+--- response_body
+hello world
+--- error_log eval
+qr/request log: \{"route_id":"1","route_name":"ctx_var-support-route_name"\}/
+
+
+
+=== TEST 32: missing `name` field, batch_max_size=1 and concat_method is json
+--- 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": {
+                        "http-logger": {
+                            "uri": "http://127.0.0.1:1980/log",
+                            "batch_max_size": 1,
+                            "max_retry_count": 1,
+                            "retry_delay": 2,
+                            "buffer_duration": 2,
+                            "concat_method": "json"
+                        }
+                    },
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:1982": 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 33: hit route and report http logger
+--- request
+GET /hello
+--- response_body
+hello world
+--- error_log eval
+qr/request log: \{"route_id":"1"\}/