前天写了一个日志记录的插件,是将接口请求和返回的一些相关内容,以指定的数据格式写入到文件,方便大数据使用 Filebeat 读取,并显示在 ELK,话不多说上代码。
schema.lua
local typedefs = require "kong.db.schema.typedefs"
return {
name = "file-log",
fields = {
{ protocols = typedefs.protocols_http },
{ config = {
type = "record",
fields = {
{ path = { type = "string",
required = true,
match = [[^[^*&%%\`]+$]],
err = "not a valid filename",
}, },
{ reopen = { type = "boolean", default = false }, },
}, }, },
}
}
handler.lua
local kong = kong
local ffi = require "ffi"
local zlib = require("zlib")
local cjson = require "cjson"
local concat = table.concat
local system_constants = require "lua_system_constants"
local O_CREAT = system_constants.O_CREAT()
local O_WRONLY = system_constants.O_WRONLY()
local O_APPEND = system_constants.O_APPEND()
local S_IRUSR = system_constants.S_IRUSR()
local S_IWUSR = system_constants.S_IWUSR()
local S_IRGRP = system_constants.S_IRGRP()
local S_IROTH = system_constants.S_IROTH()
local oflags = bit.bor(O_WRONLY, O_CREAT, O_APPEND)
local mode = bit.bor(S_IRUSR, S_IWUSR, S_IRGRP, S_IROTH)
local C = ffi.C
ffi.cdef [[
int write(int fd, const void * ptr, int numbytes);
]]
-- fd tracking utility functions
local file_descriptors = {}
local FileLogHandler = {}
FileLogHandler.PRIORITY = 9
FileLogHandler.VERSION = "2.0.1"
function FileLogHandler:access(conf)
kong.ctx.shared.access_time = ngx.now()
end
function FileLogHandler:body_filter(conf)
local ctx = ngx.ctx
local chunk, eof = ngx.arg[1], ngx.arg[2]
local uncompress
ctx.rt_body_chunks = ctx.rt_body_chunks or {}
ctx.rt_body_chunk_number = ctx.rt_body_chunk_number or 1
if eof then
local chunks = concat(ctx.rt_body_chunks)
local encoding = kong.response.get_header("Content-Encoding")
if encoding == "gzip" then
uncompress = zlib.inflate()(chunks)
end
kong.ctx.shared.respbody = uncompress or chunks
ngx.arg[1] = chunks
else
ctx.rt_body_chunks[ctx.rt_body_chunk_number] = chunk
ctx.rt_body_chunk_number = ctx.rt_body_chunk_number + 1
ngx.arg[1] = nil
end
end
function FileLogHandler:log(conf)
-- local message = serialize(ngx)
local data
data = ngx.req.get_body_data()
local logs = {
client_ip = kong.client.get_ip(),
client_forwarded_ip = kong.client.get_forwarded_ip(),
request_scheme = kong.request.get_scheme(),
request_host = kong.request.get_host(),
request_method = kong.request.get_method(),
request_path = kong.request.get_path(),
request_headers = kong.request.get_headers(),
request_sunmi_id = kong.ctx.shared.sunmi_id,
request_sunmi_shopid = kong.ctx.shared.sunmi_shopid,
request_raw_body = data,
response_status = kong.response.get_status(),
response_headers = kong.response.get_headers(),
response_body = kong.ctx.shared.respbody,
process_time = 0,
time = 0
}
if kong.ctx.shared.access_time ~= nil then
logs.process_time = (ngx.now() - kong.ctx.shared.access_time)
logs.time = kong.ctx.shared.access_time
end
local msg = cjson.encode(logs) .. "\n"
local fd = file_descriptors[conf.path]
if fd and conf.reopen then
C.close(fd)
file_descriptors[conf.path] = nil
fd = nil
end
if not fd then
fd = C.open(conf.path, oflags, mode)
if fd < 0 then
local errno = ffi.errno()
ngx.log(ngx.ERR, "[file-log] failed to open the file: ", ffi.string(C.strerror(errno)))
else
file_descriptors[conf.path] = fd
end
end
C.write(fd, msg, #msg)
end
return FileLogHandler
如下图,设置路径开启后,请求相关的信息会写入到你设置的路径文件中。
你好,我配置file-log,日志中一直有[kong] handler.lua:56 [file-log] failed to open the file: No such file or directory while logging request报错,请问是什么问题
最近也准备用kong , 很想问下 serveless 的pre-function 代码中如何发起http请求 进行, 真没有看到如何reuqire http包 本身kong 自带的lua类库好像没有 OωO
看你有没有安转openresty,如果安装了直接引用 resty.http 就可以发起http请求了