123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- -- 检查是否已标记需要记录请求(由前面的逻辑设置 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
|