Openresty使用Log_by_lua推送数据到Syslog服务器

2.2k 词

LOG_BY_LUA推送数据到Syslog服务器

正文:

Openresy的resty_logger组件,提供了一种可能,就是在Openresty的Log阶段,推送数据到syslog-ng服务器上,Openresty的执行阶段,其实是一种虚拟化的逻辑业务划分,如果从TCP数据包的角度来看,是分不出什么init, content,log等阶段,而log阶段应该是所有的Openresty执行阶段的最后一个阶段,关于执行阶段的顺序,可以参照下面的这个图:

Openresty执行阶段

对于resty-logger的执行处理,如果要划分几大处理的话,可以分成, syslog服务器信息定义,初始化连接,写入log数据。可以在代码中,比较清晰的看出来,官方的例子如下,一些参数进行了调整:

log_by_lua '
           local logger = require "resty.logger.socket"
           ngx.log(ngx.ERR, "Test Syslog: ", "call")
           if not logger.initted() then
               local ok, err = logger.init {
                   host="127.0.0.1",
                   port=810,
                   sock_type="udp",
                   flush_limit = 1,
                   --drop_limit = 5678
               }
               if not ok then
                   ngx.log(ngx.ERR, "failed to initialize the logger: ", err)
                   return
               end
           end

           -- construct the custom access log message in
           -- the Lua variable "msg"
           local bytes, err = logger.log("test")
           if err then
               ngx.log(ngx.ERR, "failed to log message: ", err)
               return
           end
       ';

上面的代码,需要注意的是 flush_limit 这个参数,在实际的联动Openresty和Syslog-ng服务的过程中,可能更希望看到实时写入效果,比如说, 用tail -f 监控syslog-ng端的日志服务,然后在浏览器中,请求Openresty的WEB服务,访问一次,syslog文件就写入一条,如果是这样话,需要把flush_limit,设置等于1,不然会,等待log数据积攒到一定的数据(我们自己指定,>1)才向syslog服务器的服务端口推送一次。

此阶段有那些数据可输出?

做一个小实验,以下的API,都可以在这个阶段调用。

-- construct the custom access log message in
-- the Lua variable "msg"
local url = ngx.var.uri
local method = ngx.req.get_method()
local headers = ngx.req.raw_header(true)
-- tbl
local params_var = ngx.req.get_uri_args()
local client_ip = ngx.var.remote_addr
-- tbl
local body_var = ngx.req.get_post_args()
local user_agent = ngx.req.get_headers()["User-Agent"]
local referer = ngx.req.get_headers()["Referer"]
local cookies = ngx.req.get_headers()["Cookie"]

这样就可以把这些数据,通过“分隔符”推送到syslog-ng服务器上,然后用logstash安照正则,分词解开,将对应的字段,以JSON形式存到ES里。

local bytes, err = logger.log(client_ip.." "..table.concat(params_var).." "..table.concat(body_var).." "..user_agent.." "..referer.." "..cookies.." "..url.." "..method)

后记:

上面的table.concat的数据其实连在一起时,会对解析产生困扰,最好不用,此处只是为了简单的实验用。

最后,没有给出完整的代码,直接把logger.log手动的替换一下,就可以完成这个实验,剩下就是自定义和整合问题。

如果是用Logstash向ES导入数据,也可不使用这种方式,直接使用远程代理的方式向远端口的ES导入数据。而使用这种,会涉及到修改Openresty的Conf中的代理代码,好处是可以更细致的定制log输出的格式。