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"\}/