log.lua 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. -- 检查是否已标记需要记录请求(由前面的逻辑设置 ngx.ctx.log_request 为 true)
  2. if ngx.ctx.log_request then
  3. -- 引入 cjson 库,用于将 Lua 表结构编码为 JSON 字符串
  4. local cjson = require "cjson"
  5. -- 获取请求的 URI 参数(即 URL 查询参数)
  6. local args = ngx.req.get_uri_args()
  7. -- 初始化 query_string 变量,用于存储查询参数的 JSON 字符串
  8. local query_string = ""
  9. -- 使用 pcall 安全地执行编码操作,防止因数据问题导致崩溃
  10. pcall(function()
  11. query_string = cjson.encode(args)
  12. end)
  13. -- 获取请求头信息
  14. local request_headers = ngx.req.get_headers()
  15. -- 从请求头或查询参数中提取 token 或 data 相关字段,用于日志标识
  16. local token = request_headers["token"] or args["token"] or args["data"] or args["amp;data"] or ""
  17. -- 获取请求内容类型
  18. local request_content_type = request_headers["content-type"] or ""
  19. -- 获取响应头信息
  20. local response_headers = ngx.resp.get_headers()
  21. -- 获取响应内容类型
  22. local response_content_type = response_headers["content-type"] or ""
  23. -- 初始化请求体变量
  24. local request_body = ""
  25. -- 如果请求内容类型为 application/json,则尝试获取请求体内容
  26. if request_content_type:match("application/json") then
  27. request_body = ngx.var.request_body or ""
  28. end
  29. -- 初始化响应体变量
  30. local response_body = ""
  31. -- 如果响应内容类型为 application/json,则从上下文中获取已缓存的响应体
  32. if response_content_type:match("application/json") then
  33. response_body = ngx.ctx.response_body or ""
  34. end
  35. -- 初始化请求头的 JSON 字符串
  36. request_headers_json = ""
  37. -- 安全地将请求头表编码为 JSON 字符串
  38. pcall(function()
  39. request_headers_json = cjson.encode(request_headers)
  40. end)
  41. -- 初始化响应头的 JSON 字符串
  42. response_headers_json = ""
  43. -- 安全地将响应头表编码为 JSON 字符串
  44. pcall(function()
  45. response_headers_json = cjson.encode(response_headers)
  46. end)
  47. -- 引入 resty.logger.socket 模块,用于异步发送日志
  48. local logger = require "resty.logger.socket"
  49. -- 检查 logger 是否已经初始化
  50. if not logger.initted() then
  51. -- 如果未初始化,则进行初始化配置
  52. local ok, err = logger.init{
  53. host = "127.0.0.1", -- 日志接收服务器地址
  54. port = 39876, -- 日志接收端口
  55. sock_type = "tcp", -- 使用 TCP 协议
  56. flush_limit = 10240, -- 缓冲区刷新阈值(字节)
  57. drop_limit = 1048576, -- 超过此值则丢弃新日志
  58. timeout = 1000, -- 发送超时时间(毫秒)
  59. max_retry_times = 3, -- 最大重试次数
  60. retry_interval = 10000 -- 重试间隔(毫秒)
  61. }
  62. -- 如果初始化失败,记录错误日志并退出
  63. if not ok then
  64. ngx.log(ngx.ERR, "Logger初始化失败: ", err)
  65. return
  66. end
  67. end
  68. -- 构建要记录的日志数据结构(Lua 表)
  69. local log_data = {
  70. access_time = ngx.var.time_iso8601, -- 访问时间(ISO8601 格式)
  71. status = ngx.var.status, -- HTTP 状态码
  72. request_time = ngx.var.request_time, -- 请求处理时间(秒)
  73. uri = ngx.var.uri, -- 请求的 URI
  74. query_string = query_string, -- 查询参数(JSON 字符串)
  75. request_body = request_body, -- 请求体内容
  76. request_headers = request_headers_json, -- 请求头(JSON 字符串)
  77. response_headers = response_headers_json, -- 响应头(JSON 字符串)
  78. response_body = response_body, -- 响应体内容
  79. token = token, -- 提取的 token 或 data 信息
  80. request_method = ngx.var.request_method, -- 请求方法(GET、POST 等)
  81. scheme = ngx.var.scheme, -- 协议(http 或 https)
  82. server_protocol = ngx.var.server_protocol, -- 使用的协议版本(如 HTTP/1.1)
  83. request_length = ngx.var.request_length, -- 请求长度(字节)
  84. body_bytes_sent = ngx.var.body_bytes_sent, -- 发送给客户端的响应体字节数
  85. bytes_sent = ngx.var.bytes_sent, -- 总共发送的字节数
  86. http_x_real_ip = ngx.var.http_x_real_ip, -- X-Real-IP 请求头
  87. http_x_forwarded_for = ngx.var.http_x_forwarded_for, -- X-Forwarded-For 请求头
  88. remote_addr = ngx.var.remote_addr -- 客户端真实 IP 地址
  89. }
  90. -- 使用 pcall 安全地将 log_data 编码为 JSON 字符串
  91. local success, result = pcall(cjson.encode, log_data)
  92. if not success then
  93. -- 如果编码失败,打印错误信息并返回
  94. print("JSON编码失败: ", result)
  95. return
  96. end
  97. -- 将编码后的 JSON 日志数据加上换行符发送出去
  98. local bytes, err = logger.log(result .. "\n")
  99. if err then
  100. -- 如果发送失败,记录错误日志
  101. ngx.log(ngx.ERR, "日志发送失败: ", err)
  102. end
  103. end