Skip to content

Commit 2335e92

Browse files
authored
feat(file-logger): add path properties to file-logger plugin metadata (#12825)
1 parent b7d27db commit 2335e92

File tree

4 files changed

+121
-8
lines changed

4 files changed

+121
-8
lines changed

apisix/plugins/file-logger.lua

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
--
1717
local log_util = require("apisix.utils.log-util")
1818
local core = require("apisix.core")
19+
local plugin = require("apisix.plugin")
1920
local expr = require("resty.expr.v1")
2021
local ngx = ngx
2122
local io_open = io.open
@@ -56,13 +57,15 @@ local schema = {
5657
},
5758
}
5859
},
59-
required = {"path"}
6060
}
6161

6262

6363
local metadata_schema = {
6464
type = "object",
6565
properties = {
66+
path = {
67+
type = "string"
68+
},
6669
log_format = {
6770
type = "object"
6871
}
@@ -79,17 +82,43 @@ local _M = {
7982
}
8083

8184

85+
local function get_configured_path(conf)
86+
if conf.path then
87+
return conf.path
88+
end
89+
90+
local metadata = plugin.plugin_metadata(plugin_name)
91+
if metadata and metadata.value and metadata.value.path then
92+
return metadata.value.path
93+
end
94+
95+
return nil, "property \"path\" is not set in either the plugin conf or the metadata"
96+
end
97+
98+
8299
function _M.check_schema(conf, schema_type)
83100
if schema_type == core.schema.TYPE_METADATA then
84101
return core.schema.check(metadata_schema, conf)
85102
end
103+
86104
if conf.match then
87105
local ok, err = expr.new(conf.match)
88106
if not ok then
89107
return nil, "failed to validate the 'match' expression: " .. err
90108
end
91109
end
92-
return core.schema.check(schema, conf)
110+
111+
local ok, err = core.schema.check(schema, conf)
112+
if not ok then
113+
return ok, err
114+
end
115+
116+
local path, err = get_configured_path(conf)
117+
if not path then
118+
return nil, err
119+
end
120+
121+
return true
93122
end
94123

95124

@@ -139,17 +168,24 @@ end
139168

140169

141170
local function write_file_data(conf, log_message)
171+
local path, err = get_configured_path(conf)
172+
if not path then
173+
core.log.error(err)
174+
return
175+
end
176+
142177
local msg = core.json.encode(log_message)
143178

144179
local file, err
180+
local file_conf = conf.path and conf or {path = path}
145181
if open_file_cache then
146-
file, err = open_file_cache(conf)
182+
file, err = open_file_cache(file_conf)
147183
else
148-
file, err = io_open(conf.path, 'a+')
184+
file, err = io_open(path, 'a+')
149185
end
150186

151187
if not file then
152-
core.log.error("failed to open file: ", conf.path, ", error info: ", err)
188+
core.log.error("failed to open file: ", path, ", error info: ", err)
153189
else
154190
-- file:write(msg, "\n") will call fwrite several times
155191
-- which will cause problem with the log output
@@ -158,7 +194,7 @@ local function write_file_data(conf, log_message)
158194
-- write to file directly, no need flush
159195
local ok, err = file:write(msg)
160196
if not ok then
161-
core.log.error("failed to write file: ", conf.path, ", error info: ", err)
197+
core.log.error("failed to write file: ", path, ", error info: ", err)
162198
end
163199

164200
-- file will be closed by gc, if open_file_cache exists

docs/en/latest/plugins/file-logger.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ You can also set the format of the logs by configuring the Plugin metadata. The
103103

104104
| Name | Type | Required | Default | Description |
105105
| ---------- | ------ | -------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
106+
| path | string | False | | Log file path used when the Plugin configuration does not specify `path`. |
106107
| log_format | object | False | | Log format declared as key-value pairs in JSON. Values support strings and nested objects (up to five levels deep; deeper fields are truncated). Within strings, [APISIX](../apisix-variable.md) or [NGINX](http://nginx.org/en/docs/varindex.html) variables can be referenced by prefixing with `$`. |
107108

108109
The example below shows how you can configure through the Admin API:
@@ -119,6 +120,7 @@ admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"/
119120
```shell
120121
curl http://127.0.0.1:9180/apisix/admin/plugin_metadata/file-logger -H "X-API-KEY: $admin_key" -X PUT -d '
121122
{
123+
"path": "logs/metadata-file.log",
122124
"log_format": {
123125
"host": "$host",
124126
"@timestamp": "$time_iso8601",

docs/zh/latest/plugins/file-logger.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ description: API 网关 Apache APISIX file-logger 插件可用于将日志数据
103103

104104
| 名称 | 类型 | 必选项 | 默认值 | 有效值 | 描述 |
105105
| ---------------- | ------- | ------ | ------------- | ------- | ------------------------------------------------ |
106+
| path | string || | | 当插件配置中未指定 `path` 时使用的日志文件路径。 |
106107
| log_format | object | 可选 | | | 日志格式以 JSON 的键值对声明。值支持字符串和嵌套对象(最多五层,超出部分将被截断)。字符串中可通过在前面加上 `$` 来引用 [APISIX 变量](../../../en/latest/apisix-variable.md)[NGINX 内置变量](http://nginx.org/en/docs/varindex.html)|
107108

108109
:::note 注意
@@ -127,6 +128,7 @@ admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"/
127128
curl http://127.0.0.1:9180/apisix/admin/plugin_metadata/file-logger \
128129
-H "X-API-KEY: $admin_key" -X PUT -d '
129130
{
131+
"path": "logs/metadata-file.log",
130132
"log_format": {
131133
"host": "$host",
132134
"@timestamp": "$time_iso8601",

t/plugin/file-logger.t

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ __DATA__
4141
{
4242
path = "file.log"
4343
},
44-
-- property "path" is required
44+
-- property "path" is not set in either the plugin conf or the metadata
4545
{
4646
path = nil
4747
}
@@ -61,7 +61,7 @@ __DATA__
6161
}
6262
--- response_body_like
6363
done
64-
property "path" is required
64+
property "path" is not set in either the plugin conf or the metadata
6565
6666
6767
@@ -499,3 +499,76 @@ nested log format success
499499
depth limit enforced
500500
--- error_log
501501
log_format nesting exceeds max depth 5, truncating
502+
503+
504+
505+
=== TEST 13: configure metadata path
506+
--- config
507+
location /t {
508+
content_by_lua_block {
509+
local t = require("lib.test_admin").test
510+
local code, body = t('/apisix/admin/plugin_metadata/file-logger',
511+
ngx.HTTP_PUT,
512+
[[{
513+
"path": "file-from-metadata.log"
514+
}]]
515+
)
516+
517+
if code >= 300 then
518+
ngx.status = code
519+
end
520+
ngx.say(body)
521+
}
522+
}
523+
--- response_body
524+
passed
525+
526+
527+
528+
=== TEST 14: use metadata path when plugin config does not set it
529+
--- config
530+
location /t {
531+
content_by_lua_block {
532+
local core = require("apisix.core")
533+
local t = require("lib.test_admin").test
534+
local code, body = t('/apisix/admin/routes/1',
535+
ngx.HTTP_PUT,
536+
[[{
537+
"plugins": {
538+
"file-logger": {}
539+
},
540+
"upstream": {
541+
"nodes": {
542+
"127.0.0.1:1982": 1
543+
},
544+
"type": "roundrobin"
545+
},
546+
"uri": "/hello"
547+
}]]
548+
)
549+
550+
if code >= 300 then
551+
ngx.status = code
552+
ngx.say(body)
553+
return
554+
end
555+
556+
local res_code = t("/hello", ngx.HTTP_GET)
557+
local fd, err = io.open("file-from-metadata.log", 'r')
558+
if not fd then
559+
core.log.error("failed to open file: file-from-metadata.log, error info: ", err)
560+
return
561+
end
562+
563+
local msg = fd:read()
564+
fd:close()
565+
566+
local new_msg = core.json.decode(msg)
567+
if new_msg and new_msg.route_id == '1' then
568+
ngx.status = res_code
569+
ngx.say("write file log success")
570+
end
571+
}
572+
}
573+
--- response_body
574+
write file log success

0 commit comments

Comments
 (0)