Hello.
Our task is to get real time statistics of web requests. But we also
serve large video files. Thus I think we should log continuous requests
during execution for example every second. And frequently upload logs to
statistics. It is not possible to log a request multiple times during
its execution with nginx itself. I've found a solution with lua module:
body_filter_by_lua '
ngx.ctx.len = ngx.ctx.len + string.len(ngx.arg[1])
ngx.update_time()
ngx.ctx.now = ngx.now()
if ngx.ctx.now > ngx.ctx.now_prev + 1 -- seconds
then
ngx.ctx.realtime_log:write(
...
ngx.ctx.realtime_log:flush()
Earlier in rewrite_by_lua section I've opened ngx.ctx.realtime_log for
appending and initialized ngx.ctx.len and other counters. Later in
log_by_lua we are logging the end of request and close log file. I've
attached nginx config file, it works ok.
But I'd prefer not to write log file, but send logs directly into redis.
Unfortunately redis operations cannot be used within body_filter_by_lua
section. As I understand, it concerns all cosocket interfaces. Is it a
principal restriction? Or are you going to implement it in future? Or is
there some workaround?
Thanks in advance. And sorry for my bad english.
Alexey Nalbat.
worker_processes 1;
error_log logs/error.log;
events {
worker_connections 1024;
}
http {
server {
listen 8080;
location / {
autoindex on;
rewrite_by_lua '
ngx.ctx.len_prev = 0
ngx.ctx.now_prev = ngx.now()
ngx.ctx.len = 0
ngx.ctx.now = ngx.now()
ngx.ctx.torso_id = 1
ngx.ctx.request_id = ngx.md5(
ngx.ctx.now
.. ngx.var.remote_addr
.. ngx.var.uri
)
local req_length = string.len(
ngx.var.uri
-- .. "..."
)
local req_headers = ngx.req.get_headers()
for k, v in pairs(req_headers) do
req_length = req_length + string.len( k .. v )
end
ngx.req.read_body()
local req_body = ngx.req.get_body_data()
if req_body ~= nil then
req_length = req_length + string.len( req_body )
end
ngx.ctx.realtime_log = assert(io.open("logs/realtime.log", "a"))
ngx.ctx.realtime_log:write(
ngx.ctx.now, -- текущее время в формате YYYY-MM-DD HH:MI:SS
"\\t", ngx.ctx.request_id, -- uuid, общий для строк с разными EVENT_STATE одного и того же запроса
"\\t", "start", -- START, FLUSH, STOP
"\\t", req_length, -- кол-во полученных байт
"\\t", ngx.ctx.len-ngx.ctx.len_prev, -- кол-во переданных байт
"\\t", ngx.ctx.now-ngx.ctx.now_prev, -- длительность в секундах, для продолжительного события
"\\t", "http", -- протокол между веб-пользователем и torso: HTTP, RTMP,..
"\\t", "SOURCE", -- cached, origin, mid-origin
"\\t", "STATUS", -- OK, ERROR или HTTP-статус
"\\t", "nginx", -- nginx или wowza
"\\t", ngx.ctx.torso_id, -- идентификатор сервера показа
"\\t", ngx.var.uri, -- урл на нашем сервере показа, запрошенный веб-пользователем
"\\t", "CLIENT_ID", -- идентификатор клиента
"\\t", "http", -- протокол между torso и origin
"\\t", "CLIENT_URI", -- урл на сайте клиента
"\\t", "REFERER", -- урл-реферер на сайте криента
"\\t", ngx.var.remote_addr, -- ip-адрес веб-пользователя, в том числе через прокси
"\\t", "USER_ID", -- идентификатор пользователя
"\\t", "SESSION_ID", -- идентификатор сессии
"\\t", ngx.var.http_user_agent, -- юзерагент пользователя
"\\n" )
ngx.ctx.realtime_log:flush()
';
body_filter_by_lua '
ngx.ctx.len = ngx.ctx.len + string.len(ngx.arg[1])
ngx.update_time()
ngx.ctx.now = ngx.now()
if ngx.ctx.now > ngx.ctx.now_prev + 1 -- seconds
-- or ngx.ctx.len > ngx.ctx.len_prev + 10000000 -- bytes
then
ngx.ctx.realtime_log:write(
ngx.ctx.now, -- текущее время в формате YYYY-MM-DD HH:MI:SS
"\\t", ngx.ctx.request_id, -- uuid, общий для строк с разными EVENT_STATE одного и того же запроса
"\\t", "flush", -- START, FLUSH, STOP
"\\t", "0", -- кол-во полученных байт
"\\t", ngx.ctx.len-ngx.ctx.len_prev, -- кол-во переданных байт
"\\t", ngx.ctx.now-ngx.ctx.now_prev, -- длительность в секундах, для продолжительного события
"\\n" )
ngx.ctx.realtime_log:flush()
ngx.ctx.len_prev = ngx.ctx.len
ngx.ctx.now_prev = ngx.ctx.now
end
';
log_by_lua '
ngx.ctx.realtime_log:write(
ngx.ctx.now, -- текущее время в формате YYYY-MM-DD HH:MI:SS
"\\t", ngx.ctx.request_id, -- uuid, общий для строк с разными EVENT_STATE одного и того же запроса
"\\t", "stop", -- START, FLUSH, STOP
"\\t", "0", -- кол-во полученных байт
"\\t", ngx.ctx.len-ngx.ctx.len_prev, -- кол-во переданных байт
"\\t", ngx.ctx.now-ngx.ctx.now_prev, -- длительность в секундах, для продолжительного события
"\\n" )
ngx.ctx.realtime_log:flush()
ngx.ctx.realtime_log:close()
';
}
}
}