-- 检查是否已标记需要记录请求(由前面的逻辑设置 ngx.ctx.log_request 为 true) if ngx.ctx.log_request then -- 引入 cjson 库,用于将 Lua 表结构编码为 JSON 字符串 local cjson = require "cjson" -- 获取请求的 URI 参数(即 URL 查询参数) local args = ngx.req.get_uri_args() -- 初始化 query_string 变量,用于存储查询参数的 JSON 字符串 local query_string = "" -- 使用 pcall 安全地执行编码操作,防止因数据问题导致崩溃 pcall(function() query_string = cjson.encode(args) end) -- 获取请求头信息 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 request_content_type = request_headers["content-type"] or "" -- 获取响应头信息 local response_headers = ngx.resp.get_headers() -- 获取响应内容类型 local response_content_type = response_headers["content-type"] or "" -- 初始化请求体变量 local request_body = "" -- 如果请求内容类型为 application/json,则尝试获取请求体内容 if request_content_type:match("application/json") then request_body = ngx.var.request_body or "" end -- 初始化响应体变量 local response_body = "" -- 如果响应内容类型为 application/json,则从上下文中获取已缓存的响应体 if response_content_type:match("application/json") then response_body = ngx.ctx.response_body or "" end -- 初始化请求头的 JSON 字符串 request_headers_json = "" -- 安全地将请求头表编码为 JSON 字符串 pcall(function() request_headers_json = cjson.encode(request_headers) end) -- 初始化响应头的 JSON 字符串 response_headers_json = "" -- 安全地将响应头表编码为 JSON 字符串 pcall(function() response_headers_json = cjson.encode(response_headers) end) -- 引入 resty.logger.socket 模块,用于异步发送日志 local logger = require "resty.logger.socket" -- 检查 logger 是否已经初始化 if not logger.initted() then -- 如果未初始化,则进行初始化配置 local ok, err = logger.init{ 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 ngx.log(ngx.ERR, "Logger初始化失败: ", err) return end end -- 构建要记录的日志数据结构(Lua 表) local log_data = { 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) if not success then -- 如果编码失败,打印错误信息并返回 print("JSON编码失败: ", result) return end -- 将编码后的 JSON 日志数据加上换行符发送出去 local bytes, err = logger.log(result .. "\n") if err then -- 如果发送失败,记录错误日志 ngx.log(ngx.ERR, "日志发送失败: ", err) end end