Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions apisix/utils/log-util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ end
local function gen_log_format(format)
local log_format = {}
for k, var_name in pairs(format) do
if var_name:byte(1, 1) == str_byte("$") then
if type(var_name) == "table" then
local nested_format = gen_log_format(var_name)
log_format[k] = {false, nested_format}
elseif type(var_name) == "string" and var_name:byte(1, 1) == str_byte("$") then
log_format[k] = {true, var_name:sub(2)}
else
log_format[k] = {false, var_name}
Expand All @@ -83,8 +86,7 @@ local function gen_log_format(format)
end


local function get_custom_format_log(ctx, format, max_req_body_bytes)
local log_format = lru_log_format(format or "", nil, gen_log_format, format)
local function build_log_entry(ctx, log_format, max_req_body_bytes)
local entry = core.table.new(0, core.table.nkeys(log_format))
for k, var_attr in pairs(log_format) do
if var_attr[1] then
Expand All @@ -100,10 +102,19 @@ local function get_custom_format_log(ctx, format, max_req_body_bytes)
else
entry[k] = ctx.var[var_attr[2]]
end
elseif type(var_attr[2]) == "table" then
entry[k] = build_log_entry(ctx, var_attr[2], max_req_body_bytes)
else
entry[k] = var_attr[2]
end
end
return entry
end


local function get_custom_format_log(ctx, format, max_req_body_bytes)
local log_format = lru_log_format(format or "", nil, gen_log_format, format)
local entry = build_log_entry(ctx, log_format, max_req_body_bytes)

local matched_route = ctx.matched_route and ctx.matched_route.value
if matched_route then
Expand Down
91 changes: 91 additions & 0 deletions t/plugin/file-logger.t
Original file line number Diff line number Diff line change
Expand Up @@ -338,3 +338,94 @@ passed
}
--- response_body
write file log success



=== TEST 10: nested log format in plugin
--- 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-logger-nested.log",
"log_format": {
"host": "$host",
"client_ip": "$remote_addr",
"request": {
"method": "$request_method",
"uri": "$request_uri",
"headers": {
"user_agent": "$http_user_agent"
}
},
"response": {
"status": "$status"
}
}
}
},
"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 11: verify nested log format structure
--- config
location /t {
content_by_lua_block {
local core = require("apisix.core")
local t = require("lib.test_admin").test
local code = t("/hello", ngx.HTTP_GET)
local fd, err = io.open("file-logger-nested.log", 'r')
local msg

if not fd then
core.log.error("failed to open file: file-logger-nested.log, error info: ", err)
return
end

msg = fd:read()
fd:close()

local new_msg = core.json.decode(msg)
if new_msg.host == '127.0.0.1' and
new_msg.client_ip == '127.0.0.1' and
type(new_msg.request) == "table" and
new_msg.request.method == 'GET' and
new_msg.request.uri == '/hello' and
type(new_msg.request.headers) == "table" and
new_msg.request.headers.user_agent and
type(new_msg.response) == "table" and
new_msg.response.status == 200 and
new_msg.route_id == '1'
then
msg = "nested log format success"
ngx.status = code
ngx.say(msg)
else
ngx.say("nested log format failed")
end
}
}
--- response_body
nested log format success
75 changes: 75 additions & 0 deletions t/plugin/http-logger-log-format.t
Original file line number Diff line number Diff line change
Expand Up @@ -567,3 +567,78 @@ passed
tail -n 1 ci/pod/vector/http.log
--- response_body eval
qr/"x_ip":"127.0.0.1".*\}/



=== TEST 19: nested log format in plugin
--- 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:3001",
"batch_max_size": 1,
"max_retry_count": 1,
"retry_delay": 2,
"buffer_duration": 2,
"inactive_timeout": 2,
"concat_method": "json",
"log_format": {
"host": "$host",
"client_ip": "$remote_addr",
"request": {
"method": "$request_method",
"uri": "$request_uri",
"headers": {
"user_agent": "$http_user_agent"
}
},
"response": {
"status": "$status"
}
}
}
},
"upstream": {
"nodes": {
"127.0.0.1:1982": 1
},
"type": "roundrobin"
},
"uri": "/hello"
}]]
)

if code >= 300 then
ngx.status = code
end

local code, _, body2 = t("/hello", "GET")
if code >= 300 then
ngx.status = code
ngx.say("fail")
return
end
ngx.say(body)
}
}
--- request
GET /t
--- response_body
passed



=== TEST 20: hit route and verify nested log format
--- exec
tail -n 1 ci/pod/vector/http.log
--- response_body eval
qr/"client_ip":"127\.0\.0\.1"/ and
qr/"request":\{[^}]*"method":"GET"/ and
qr/"request":\{[^}]*"uri":"\/hello"/ and
qr/"response":\{[^}]*"status":200/ and
qr/"host":"127\.0\.0\.1"/
Loading