Kong的日志记录(log)自定义插件

    技术2023-03-27  104

    转载 李亚飞 大佬的文章:https://www.lyafei.com/archives/301/

    Kong的日志记录(log)自定义插件

    前天写了一个日志记录的插件,是将接口请求和返回的一些相关内容,以指定的数据格式写入到文件,方便大数据使用 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
    如下图,设置路径开启后,请求相关的信息会写入到你设置的路径文件中。

    Processed: 0.011, SQL: 9