Skip to main content
Version: 8.2405.x.x RR

Configuring a log facility using filters

Using a LuaFilter and a LoggerFilter allows you to implement your own log facility, see chapters LuaFilter and LoggerFilter. The LuaFilter might be used to create the log line which shall be logged, while the LoggerFilter defines when and to which file to write the log data.

Example:

<filter>
<filter-name>LuaDataCollector</filter-name>
<filter-class>ch::nevis::isiweb4::filter::lua::LuaFilter</filter-class>
<init-param>
<param-name>Script OutputHeaderFunctionName </param-name>
<param-value> createLogData</param-value>
</init-param>
<init-param>
<param-name>Script</param-name>
<param-value>
local timer = nevis.sys.timer.new()
responseProcessed = false

-- escapes non-printable / non 7-bit ASCII characters and double quotes
function escapeNonePrintableChars (c)
local c_byte = c:byte()
-- non printable
if c_byte > 127 then
return "0x" .. string.format("%X", c_byte)
elseif c_byte < 32 then
return "0x" .. string.format("%X", c_byte)
elseif c_byte == 34 then
return "\\\""
end
-- no change
return nil
end

function createLogData (request, response)

local frame = {}
-- timestamp:
local reqTime = timer:getTime()
local timeInMs = timer:getTime()
local timeMsPart = timeInMs%1000
local timeInS = (timeInMs - timeMsPart)/1000
local timeFormat = os.date("%Y-%m-%dT%H:%M:%S", timeInS).."."..timeMsPart
table.insert(frame, "{ \"timestamp\":\"" .. timeFormat .. "\", ")

-- userAgent:
local userAgent = request:getHeader("User-Agent")
if userAgent == nil then
userAgent = "null"
else
local escapedUserAgent = string.gsub(userAgent, "(.)", escapeNonePrintableChars)
userAgent = "\"" .. escapedUserAgent .. "\""
end
table.insert(frame, "\"userAgent\":" .. userAgent .. ", ")

-- address:
local address = request:getEnv("AD_REMOTE_ADDR")
table.insert(frame, "\"address\":\"" .. address .. "\", ")

-- HTTP method:
local method = request:getEnv("REQUEST_METHOD")
if method == nil then
method = "null"
else
method = "\"" .. method .. "\""
end
table.insert(frame, "\"method\":" .. method .. ", ")

--reqPath:
local path = request:getUri()
path = string.gsub(path, "(.)", escapeNonePrintableChars)
table.insert(frame, "\"reqPath\":\"" .. path .. "\", ")

-- client id:
local clID = request:getEnv("bcx.servlet.session.HttpSessionId")
if clID == nil then
clID = "null"
else
clID = "\"" .. clID .. "\""
end
table.insert(frame, "\"clID\":" .. clID .. ", ")

-- transaction id:
local trID = request:getEnv("UNIQUE_ID")
if trID == nil then
trID = "null"
else
trID = "\"" .. trID .. "\""
end
table.insert(frame, "\"trID\":" .. trID .. " }")

local logLine = table.concat(frame)
-- store the data within the "LOGLINE" variable:
request:setEnv("LOGLINE", logLine)
end
</param-value>
</init-param>
</filter>

<filter>
<filter-name>Logger</filter-name>
<filter-class>ch::nevis::isiweb4::filter::audit::LoggerFilter</filter-class>
<init-param>
<param-name>FileName</param-name>
<param-value>/var/opt/nevisproxy/default/logs/custom.log</param-value>
</init-param>
<init-param>
<param-name>RotationPolicy</param-name>
<param-value>size:52428803:5</param-value>
</init-param>
<init-param>
<param-name>LogLine</param-name>
<param-value>ENV:LOGLINE;</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>Logger</filter-name>
<url-pattern>/app/*</url-pattern>
</filter-mapping>

<filter-mapping>
<filter-name>LuaDataCollector</filter-name>
<url-pattern>/app/*</url-pattern>
</filter-mapping>

Always ensure to properly encode the data to be logged according to the format definition you use.

This example can be found in examples/monitoring/data_collection.example on the installed nevisProxy package