|
@@ -1,76 +1,107 @@
|
|
|
|
+-- 检查是否已标记需要记录请求(由前面的逻辑设置 ngx.ctx.log_request 为 true)
|
|
if ngx.ctx.log_request then
|
|
if ngx.ctx.log_request then
|
|
|
|
+ -- 引入 cjson 库,用于将 Lua 表结构编码为 JSON 字符串
|
|
local cjson = require "cjson"
|
|
local cjson = require "cjson"
|
|
|
|
+ -- 获取请求的 URI 参数(即 URL 查询参数)
|
|
local args = ngx.req.get_uri_args()
|
|
local args = ngx.req.get_uri_args()
|
|
|
|
+ -- 初始化 query_string 变量,用于存储查询参数的 JSON 字符串
|
|
local query_string = ""
|
|
local query_string = ""
|
|
|
|
+ -- 使用 pcall 安全地执行编码操作,防止因数据问题导致崩溃
|
|
pcall(function()
|
|
pcall(function()
|
|
query_string = cjson.encode(args)
|
|
query_string = cjson.encode(args)
|
|
end)
|
|
end)
|
|
|
|
+ -- 获取请求头信息
|
|
local request_headers = ngx.req.get_headers()
|
|
local request_headers = ngx.req.get_headers()
|
|
|
|
+ -- 从请求头或查询参数中提取 token 或 data 相关字段,用于日志标识
|
|
local token = request_headers["token"] or args["token"] or args["data"] or args["amp;data"] or ""
|
|
local token = request_headers["token"] or args["token"] or args["data"] or args["amp;data"] or ""
|
|
|
|
+ -- 获取请求内容类型
|
|
local request_content_type = request_headers["content-type"] or ""
|
|
local request_content_type = request_headers["content-type"] or ""
|
|
|
|
+ -- 获取响应头信息
|
|
local response_headers = ngx.resp.get_headers()
|
|
local response_headers = ngx.resp.get_headers()
|
|
|
|
+ -- 获取响应内容类型
|
|
local response_content_type = response_headers["content-type"] or ""
|
|
local response_content_type = response_headers["content-type"] or ""
|
|
|
|
+ -- 初始化请求体变量
|
|
local request_body = ""
|
|
local request_body = ""
|
|
|
|
+ -- 如果请求内容类型为 application/json,则尝试获取请求体内容
|
|
if request_content_type:match("application/json") then
|
|
if request_content_type:match("application/json") then
|
|
request_body = ngx.var.request_body or ""
|
|
request_body = ngx.var.request_body or ""
|
|
end
|
|
end
|
|
|
|
+ -- 初始化响应体变量
|
|
local response_body = ""
|
|
local response_body = ""
|
|
|
|
+ -- 如果响应内容类型为 application/json,则从上下文中获取已缓存的响应体
|
|
if response_content_type:match("application/json") then
|
|
if response_content_type:match("application/json") then
|
|
response_body = ngx.ctx.response_body or ""
|
|
response_body = ngx.ctx.response_body or ""
|
|
end
|
|
end
|
|
|
|
+ -- 初始化请求头的 JSON 字符串
|
|
request_headers_json = ""
|
|
request_headers_json = ""
|
|
|
|
+ -- 安全地将请求头表编码为 JSON 字符串
|
|
pcall(function()
|
|
pcall(function()
|
|
request_headers_json = cjson.encode(request_headers)
|
|
request_headers_json = cjson.encode(request_headers)
|
|
end)
|
|
end)
|
|
|
|
+ -- 初始化响应头的 JSON 字符串
|
|
response_headers_json = ""
|
|
response_headers_json = ""
|
|
|
|
+ -- 安全地将响应头表编码为 JSON 字符串
|
|
pcall(function()
|
|
pcall(function()
|
|
response_headers_json = cjson.encode(response_headers)
|
|
response_headers_json = cjson.encode(response_headers)
|
|
end)
|
|
end)
|
|
|
|
+
|
|
|
|
+ -- 引入 resty.logger.socket 模块,用于异步发送日志
|
|
local logger = require "resty.logger.socket"
|
|
local logger = require "resty.logger.socket"
|
|
|
|
+ -- 检查 logger 是否已经初始化
|
|
if not logger.initted() then
|
|
if not logger.initted() then
|
|
|
|
+ -- 如果未初始化,则进行初始化配置
|
|
local ok, err = logger.init{
|
|
local ok, err = logger.init{
|
|
- host = "127.0.0.1",
|
|
|
|
- port = 39876,
|
|
|
|
- sock_type = "tcp",
|
|
|
|
- flush_limit = 10240,
|
|
|
|
- drop_limit = 1048576,
|
|
|
|
- timeout = 1000,
|
|
|
|
- max_retry_times = 3,
|
|
|
|
- retry_interval = 10000
|
|
|
|
|
|
+ host = "127.0.0.1", -- 日志接收服务器地址
|
|
|
|
+ port = 39876, -- 日志接收端口
|
|
|
|
+ sock_type = "tcp", -- 使用 TCP 协议
|
|
|
|
+ flush_limit = 10240, -- 缓冲区刷新阈值(字节)
|
|
|
|
+ drop_limit = 1048576, -- 超过此值则丢弃新日志
|
|
|
|
+ timeout = 1000, -- 发送超时时间(毫秒)
|
|
|
|
+ max_retry_times = 3, -- 最大重试次数
|
|
|
|
+ retry_interval = 10000 -- 重试间隔(毫秒)
|
|
}
|
|
}
|
|
|
|
+ -- 如果初始化失败,记录错误日志并退出
|
|
if not ok then
|
|
if not ok then
|
|
ngx.log(ngx.ERR, "Logger初始化失败: ", err)
|
|
ngx.log(ngx.ERR, "Logger初始化失败: ", err)
|
|
return
|
|
return
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
+
|
|
|
|
+ -- 构建要记录的日志数据结构(Lua 表)
|
|
local log_data = {
|
|
local log_data = {
|
|
- access_time = ngx.var.time_iso8601,
|
|
|
|
- status = ngx.var.status,
|
|
|
|
- request_time = ngx.var.request_time,
|
|
|
|
- uri = ngx.var.uri,
|
|
|
|
- query_string = query_string,
|
|
|
|
- request_body = request_body,
|
|
|
|
- request_headers = request_headers_json,
|
|
|
|
- response_headers = response_headers_json,
|
|
|
|
- response_body = response_body,
|
|
|
|
- token = token,
|
|
|
|
- request_method = ngx.var.request_method,
|
|
|
|
- scheme = ngx.var.scheme,
|
|
|
|
- server_protocol = ngx.var.server_protocol,
|
|
|
|
- request_length = ngx.var.request_length,
|
|
|
|
- body_bytes_sent = ngx.var.body_bytes_sent,
|
|
|
|
- bytes_sent = ngx.var.bytes_sent,
|
|
|
|
- http_x_real_ip = ngx.var.http_x_real_ip,
|
|
|
|
- http_x_forwarded_for = ngx.var.http_x_forwarded_for,
|
|
|
|
- remote_addr = ngx.var.remote_addr
|
|
|
|
|
|
+ access_time = ngx.var.time_iso8601, -- 访问时间(ISO8601 格式)
|
|
|
|
+ status = ngx.var.status, -- HTTP 状态码
|
|
|
|
+ request_time = ngx.var.request_time, -- 请求处理时间(秒)
|
|
|
|
+ uri = ngx.var.uri, -- 请求的 URI
|
|
|
|
+ query_string = query_string, -- 查询参数(JSON 字符串)
|
|
|
|
+ request_body = request_body, -- 请求体内容
|
|
|
|
+ request_headers = request_headers_json, -- 请求头(JSON 字符串)
|
|
|
|
+ response_headers = response_headers_json, -- 响应头(JSON 字符串)
|
|
|
|
+ response_body = response_body, -- 响应体内容
|
|
|
|
+ token = token, -- 提取的 token 或 data 信息
|
|
|
|
+ request_method = ngx.var.request_method, -- 请求方法(GET、POST 等)
|
|
|
|
+ scheme = ngx.var.scheme, -- 协议(http 或 https)
|
|
|
|
+ server_protocol = ngx.var.server_protocol, -- 使用的协议版本(如 HTTP/1.1)
|
|
|
|
+ request_length = ngx.var.request_length, -- 请求长度(字节)
|
|
|
|
+ body_bytes_sent = ngx.var.body_bytes_sent, -- 发送给客户端的响应体字节数
|
|
|
|
+ bytes_sent = ngx.var.bytes_sent, -- 总共发送的字节数
|
|
|
|
+ http_x_real_ip = ngx.var.http_x_real_ip, -- X-Real-IP 请求头
|
|
|
|
+ http_x_forwarded_for = ngx.var.http_x_forwarded_for, -- X-Forwarded-For 请求头
|
|
|
|
+ remote_addr = ngx.var.remote_addr -- 客户端真实 IP 地址
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ -- 使用 pcall 安全地将 log_data 编码为 JSON 字符串
|
|
local success, result = pcall(cjson.encode, log_data)
|
|
local success, result = pcall(cjson.encode, log_data)
|
|
if not success then
|
|
if not success then
|
|
|
|
+ -- 如果编码失败,打印错误信息并返回
|
|
print("JSON编码失败: ", result)
|
|
print("JSON编码失败: ", result)
|
|
return
|
|
return
|
|
end
|
|
end
|
|
|
|
+
|
|
|
|
+ -- 将编码后的 JSON 日志数据加上换行符发送出去
|
|
local bytes, err = logger.log(result .. "\n")
|
|
local bytes, err = logger.log(result .. "\n")
|
|
if err then
|
|
if err then
|
|
|
|
+ -- 如果发送失败,记录错误日志
|
|
ngx.log(ngx.ERR, "日志发送失败: ", err)
|
|
ngx.log(ngx.ERR, "日志发送失败: ", err)
|
|
end
|
|
end
|
|
end
|
|
end
|