Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(file-logger): support standard output for file logger plugins #8681

Closed
wants to merge 11 commits into from
5 changes: 4 additions & 1 deletion apisix/cli/ops.lua
Original file line number Diff line number Diff line change
Expand Up @@ -825,7 +825,10 @@ local function start(env, ...)
init_etcd(env, args)
end

util.execute_cmd(env.openresty_args)
local data, err = util.execute_cmd(env.openresty_args)
if not err and data and data ~= "" then
print(data)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is useless to print the access log only after the Nginx exited.

end
end


Expand Down
19 changes: 15 additions & 4 deletions apisix/plugins/file-logger.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ local log_util = require("apisix.utils.log-util")
local core = require("apisix.core")
local ngx = ngx
local io_open = io.open
local io_output = io.output
local is_apisix_or, process = pcall(require, "resty.apisix.process")


local plugin_name = "file-logger"
local std_out_file = "stdout"


local schema = {
Expand Down Expand Up @@ -77,9 +79,14 @@ if is_apisix_or then
})

local function open_file_handler(conf, handler)
local file, err = io_open(conf.path, 'a+')
if not file then
return nil, err
local file, err
if conf.path == std_out_file then
file = io_output()
else
file, err = io_open(conf.path, 'a+')
if not file then
return nil, err
end
end

-- it will case output problem with buffer when log is larger than buffer
Expand Down Expand Up @@ -120,7 +127,11 @@ local function write_file_data(conf, log_message)
if open_file_cache then
file, err = open_file_cache(conf)
else
file, err = io_open(conf.path, 'a+')
if conf.path == std_out_file then
file = io_output()
else
file, err = io_open(conf.path, 'a+')
end
end

if not file then
Expand Down
3 changes: 2 additions & 1 deletion ci/linux_apisix_current_luarocks_runner.sh
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ script() {
ulimit -n -S
ulimit -n -H

for f in ./t/cli/test_*.sh; do
shopt -s globstar
for f in ./t/cli/**/test_*.sh; do
PATH="$PATH" "$f"
done
}
Expand Down
6 changes: 3 additions & 3 deletions docs/en/latest/plugins/file-logger.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ The `file-logger` Plugin is used to push log streams to a specific location.

## Attributes

| Name | Type | Required | Description |
| ---- | ------ | -------- | ------------- |
| path | string | True | Log file path. |
| Name | Type | Required | Description |
|------------------------|---------| -------- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| path | string | True | Log file path. The special value `stdout` selects the standard output. |
| 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`. |

Expand Down
10 changes: 5 additions & 5 deletions docs/zh/latest/plugins/file-logger.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ description: API 网关 Apache APISIX file-logger 插件可用于将日志数据

## 属性

| 名称 | 类型 | 必选项 | 描述 |
| ---------------- | ------- | ------ | ------------------------------------------------ |
| path | string | 是 | 自定义输出文件路径。例如:`logs/file.log`。 |
| 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` 时记录响应。 |
| 名称 | 类型 | 必选项 | 描述 |
|------------------------|---------| ------ |---------------------------------------------------------------------------------------------------------------------------------------------|
| path | string | 是 | 自定义输出文件路径。例如:`logs/file.log`。文件路径设置为 `stdout` 时日志输出到标准输出。 |
| 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` 时记录响应。 |

## 插件元数据设置

Expand Down
82 changes: 82 additions & 0 deletions t/cli/plugin/test_file_logger_std_output.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!/usr/bin/env bash

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we remove the intermediate directory, so this file can be tested without modifying the ci script?

#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

. ./t/cli/common.sh

# setup upstream server
echo '
nginx_config:
main_configuration_snippet: |
daemon off;
http_configuration_snippet: |
server {
listen 15151;
location / {
return 201 "hello";
}
}
' > conf/config.yaml

make init

tmpout=$(mktemp)
make run > "$tmpout" &

sleep 0.2

curl -k -i http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"uri": "/mock",
"methods": [
"GET"
],
"plugins": {
"file-logger": {
"path": "stdout"
}
},
"upstream": {
"nodes": [
{
"host": "127.0.0.1",
"port": 15151,
"weight": 1
}
],
"type": "roundrobin"
}
}'

code=$(curl -v -k -i -m 20 -o /dev/null -s -w %{http_code} http://127.0.0.1:9080/mock)
if [ ! $code -eq 201 ]; then
echo "failed: check mock api failed"
exit 1
fi

make stop
sleep 0.1
if [ `grep -c '"status":201' "$tmpout"` -ne '1' ]; then
echo "failed: standard output of the file-logger plugin does not match expectations"
cat "$tmpout"
rm "$tmpout"
exit 1
fi
rm "$tmpout"

echo "passed: the file-logger plugin produced the expected output"