🐳 chore(库): 增加 日志库
parent
50453c05f3
commit
674f932099
@ -0,0 +1,29 @@
|
|||||||
|
SKYNET_ROOT ?= ../../skynet
|
||||||
|
include $(SKYNET_ROOT)/platform.mk
|
||||||
|
|
||||||
|
PLAT ?= none
|
||||||
|
|
||||||
|
TARGET = ../../luaclib/lsyslog.so
|
||||||
|
|
||||||
|
ifeq ($(PLAT), macosx)
|
||||||
|
CFLAGS = -g -O2 -dynamiclib -Wl,-undefined,dynamic_lookup -std=gnu99
|
||||||
|
else
|
||||||
|
ifeq ($(PLAT), linux)
|
||||||
|
CFLAGS = -g -O2 -shared -fPIC -std=gnu99
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
LUA_LIB ?= $(SKYNET_ROOT)/3rd/lua/
|
||||||
|
LUA_INC ?= $(SKYNET_ROOT)/3rd/lua/
|
||||||
|
|
||||||
|
SRC = .
|
||||||
|
|
||||||
|
.PHONY: all clean
|
||||||
|
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
$(TARGET): $(foreach dir, $(SRC), $(wildcard $(dir)/*.c))
|
||||||
|
$(CC) $(CFLAGS) $(SHARED) -I$(LUA_INC) $^ -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o $(TARGET)
|
||||||
@ -0,0 +1,102 @@
|
|||||||
|
// #include <config.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
|
||||||
|
#include <lua.h>
|
||||||
|
#include <lauxlib.h>
|
||||||
|
#include <lualib.h>
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
lsyslog_open(lua_State *L)
|
||||||
|
{
|
||||||
|
static char *persistent_ident = NULL;
|
||||||
|
const char *ident = luaL_checkstring(L, 1);
|
||||||
|
int facility = luaL_checkinteger(L, 2);
|
||||||
|
|
||||||
|
if (persistent_ident != NULL) {
|
||||||
|
free(persistent_ident);
|
||||||
|
}
|
||||||
|
|
||||||
|
persistent_ident = strdup(ident);
|
||||||
|
openlog(persistent_ident, LOG_PID, facility);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
lsyslog_log(lua_State *L)
|
||||||
|
{
|
||||||
|
int level = luaL_checkinteger(L, 1);
|
||||||
|
const char *line = luaL_checkstring(L, 2);
|
||||||
|
|
||||||
|
syslog(level, "%s", line);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
lsyslog_close(lua_State *L)
|
||||||
|
{
|
||||||
|
closelog();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define set_field(f,v) lua_pushliteral(L, v); \
|
||||||
|
lua_setfield(L, -2, f)
|
||||||
|
#define add_constant(c) lua_pushinteger(L, LOG_##c); \
|
||||||
|
lua_setfield(L, -2, #c)
|
||||||
|
|
||||||
|
int
|
||||||
|
luaopen_lsyslog(lua_State *L)
|
||||||
|
{
|
||||||
|
const luaL_Reg API[] = {
|
||||||
|
{ "open", lsyslog_open },
|
||||||
|
{ "close", lsyslog_close },
|
||||||
|
{ "log", lsyslog_log },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
luaL_newlib(L, API);
|
||||||
|
|
||||||
|
// set_field("_COPYRIGHT", "Copyright (C) 2014 " PACKAGE_AUTHOR);
|
||||||
|
// set_field("_DESCRIPTION", PACKAGE_DESCRIPTION);
|
||||||
|
// set_field("_VERSION", PACKAGE_VERSION);
|
||||||
|
|
||||||
|
lua_newtable(L);
|
||||||
|
add_constant(AUTH);
|
||||||
|
add_constant(AUTHPRIV);
|
||||||
|
add_constant(CRON);
|
||||||
|
add_constant(DAEMON);
|
||||||
|
add_constant(FTP);
|
||||||
|
add_constant(KERN);
|
||||||
|
add_constant(LOCAL0);
|
||||||
|
add_constant(LOCAL1);
|
||||||
|
add_constant(LOCAL2);
|
||||||
|
add_constant(LOCAL3);
|
||||||
|
add_constant(LOCAL4);
|
||||||
|
add_constant(LOCAL5);
|
||||||
|
add_constant(LOCAL6);
|
||||||
|
add_constant(LOCAL7);
|
||||||
|
add_constant(LPR);
|
||||||
|
add_constant(MAIL);
|
||||||
|
add_constant(NEWS);
|
||||||
|
add_constant(SYSLOG);
|
||||||
|
add_constant(USER);
|
||||||
|
add_constant(UUCP);
|
||||||
|
lua_setfield(L, -2, "FACILITY");
|
||||||
|
|
||||||
|
lua_newtable(L);
|
||||||
|
add_constant(EMERG);
|
||||||
|
add_constant(ALERT);
|
||||||
|
add_constant(CRIT);
|
||||||
|
add_constant(ERR);
|
||||||
|
add_constant(WARNING);
|
||||||
|
add_constant(NOTICE);
|
||||||
|
add_constant(INFO);
|
||||||
|
add_constant(DEBUG);
|
||||||
|
lua_setfield(L, -2, "LEVEL");
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
@ -0,0 +1,77 @@
|
|||||||
|
-- https://github.com/hishamhm/f-strings
|
||||||
|
|
||||||
|
local F = {}
|
||||||
|
|
||||||
|
local load = load
|
||||||
|
|
||||||
|
if _VERSION == "Lua 5.1" then
|
||||||
|
load = function(code, name, _, env)
|
||||||
|
local fn, err = loadstring(code, name)
|
||||||
|
if fn then
|
||||||
|
setfenv(fn, env)
|
||||||
|
return fn
|
||||||
|
end
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function scan_using(scanner, arg, searched)
|
||||||
|
local i = 1
|
||||||
|
repeat
|
||||||
|
local name, value = scanner(arg, i)
|
||||||
|
if name == searched then
|
||||||
|
return true, value
|
||||||
|
end
|
||||||
|
i = i + 1
|
||||||
|
until name == nil
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local function snd(_, b)
|
||||||
|
return b
|
||||||
|
end
|
||||||
|
|
||||||
|
local function format(_, str)
|
||||||
|
local outer_env = _ENV and
|
||||||
|
(snd(scan_using(debug.getlocal, 3, "_ENV")) or
|
||||||
|
snd(scan_using(debug.getupvalue, debug.getinfo(2, "f").func, "_ENV")) or _ENV) or
|
||||||
|
getfenv(2)
|
||||||
|
return (str:gsub("%b{}", function(block)
|
||||||
|
local code, fmt = block:match("{(.*):(%%.*)}")
|
||||||
|
code = code or block:match("{(.*)}")
|
||||||
|
local exp_env = {}
|
||||||
|
setmetatable(exp_env, {
|
||||||
|
__index = function(_, k)
|
||||||
|
local level = 6
|
||||||
|
while true do
|
||||||
|
local funcInfo = debug.getinfo(level, "f")
|
||||||
|
if not funcInfo then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
local ok, value = scan_using(debug.getupvalue, funcInfo.func, k)
|
||||||
|
if ok then
|
||||||
|
return value
|
||||||
|
end
|
||||||
|
ok, value = scan_using(debug.getlocal, level + 1, k)
|
||||||
|
if ok then
|
||||||
|
return value
|
||||||
|
end
|
||||||
|
level = level + 1
|
||||||
|
end
|
||||||
|
return rawget(outer_env, k)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
local fn, err = load("return " .. code, "expression `" .. code .. "`", "t", exp_env)
|
||||||
|
if fn then
|
||||||
|
return fmt and string.format(fmt, fn()) or tostring(fn())
|
||||||
|
else
|
||||||
|
error(err, 0)
|
||||||
|
end
|
||||||
|
end))
|
||||||
|
end
|
||||||
|
|
||||||
|
setmetatable(F, {
|
||||||
|
__call = format,
|
||||||
|
})
|
||||||
|
|
||||||
|
return F
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Prints logging information to console
|
||||||
|
--
|
||||||
|
-- @author Thiago Costa Ponte (thiago@ideais.com.br)
|
||||||
|
--
|
||||||
|
-- @copyright 2004-2021 Kepler Project
|
||||||
|
--
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
local logging = require "zlog.logging"
|
||||||
|
|
||||||
|
function logging.console(params, ...)
|
||||||
|
params = logging.getDeprecatedParams({"logPattern"}, params, ...)
|
||||||
|
local logPattern = params.logPattern
|
||||||
|
local timestampPattern = params.timestampPattern
|
||||||
|
|
||||||
|
return logging.new(function(self, level, message)
|
||||||
|
io.stdout:write(logging.prepareLogMsg(logPattern, os.date(timestampPattern), level, message))
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
return logging.console
|
||||||
|
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Saves logging information in a file
|
||||||
|
--
|
||||||
|
-- @author Thiago Costa Ponte (thiago@ideais.com.br)
|
||||||
|
--
|
||||||
|
-- @copyright 2004-2021 Kepler Project
|
||||||
|
--
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
local logging = require "zlog.logging"
|
||||||
|
|
||||||
|
local lastFileNameDatePattern
|
||||||
|
local lastFileHandler
|
||||||
|
|
||||||
|
local buffer_mode
|
||||||
|
do
|
||||||
|
local dir_separator = _G.package.config:sub(1, 1)
|
||||||
|
local is_windows = dir_separator == '\\'
|
||||||
|
if is_windows then
|
||||||
|
-- Windows does not support "line" buffered mode, see
|
||||||
|
-- https://github.com/lunarmodules/lualogging/pull/9
|
||||||
|
buffer_mode = "no"
|
||||||
|
else
|
||||||
|
buffer_mode = "line"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local openFileLogger = function(fname, datePattern)
|
||||||
|
local filename = string.format(fname, os.date(datePattern))
|
||||||
|
if (lastFileNameDatePattern ~= filename) then
|
||||||
|
local f = io.open(filename, "a")
|
||||||
|
if (f) then
|
||||||
|
f:setvbuf(buffer_mode)
|
||||||
|
lastFileNameDatePattern = filename
|
||||||
|
lastFileHandler = f
|
||||||
|
return f
|
||||||
|
else
|
||||||
|
return nil, string.format("file `%s' could not be opened for writing", filename)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return lastFileHandler
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function logging.file(params, ...)
|
||||||
|
params = logging.getDeprecatedParams({"filename", "datePattern", "logPattern"}, params, ...)
|
||||||
|
local filename = params.filename
|
||||||
|
local datePattern = params.datePattern
|
||||||
|
local logPattern = params.logPattern
|
||||||
|
local timestampPattern = params.timestampPattern
|
||||||
|
|
||||||
|
if type(filename) ~= "string" then
|
||||||
|
filename = "zeus.log"
|
||||||
|
end
|
||||||
|
|
||||||
|
return logging.new(function(self, level, message)
|
||||||
|
local f, msg = openFileLogger(filename, datePattern)
|
||||||
|
if not f then
|
||||||
|
return nil, msg
|
||||||
|
end
|
||||||
|
local s = logging.prepareLogMsg(logPattern, os.date(timestampPattern), level, message)
|
||||||
|
f:write(s)
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
return logging.file
|
||||||
|
|
||||||
@ -0,0 +1,251 @@
|
|||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- includes a new tostring function that handles tables recursively
|
||||||
|
--
|
||||||
|
-- @author Danilo Tuler (tuler@ideais.com.br)
|
||||||
|
-- @author Andre Carregal (info@keplerproject.org)
|
||||||
|
-- @author Thiago Costa Ponte (thiago@ideais.com.br)
|
||||||
|
--
|
||||||
|
-- @copyright 2004-2021 Kepler Project
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
local type, table, string, _tostring, tonumber = type, table, string, tostring, tonumber
|
||||||
|
local select = select
|
||||||
|
local error = error
|
||||||
|
local format = string.format
|
||||||
|
local pairs = pairs
|
||||||
|
local ipairs = ipairs
|
||||||
|
|
||||||
|
local logging = {
|
||||||
|
-- Meta information
|
||||||
|
_COPYRIGHT = "Copyright (C) 2004-2021 Kepler Project",
|
||||||
|
_DESCRIPTION = "A simple API to use logging features in Lua",
|
||||||
|
_VERSION = "LuaLogging 1.5.1",
|
||||||
|
}
|
||||||
|
|
||||||
|
local LEVELS = {"DEBUG", "INFO", "WARN", "ERROR", "FATAL", "OFF"}
|
||||||
|
local MAX_LEVELS = #LEVELS
|
||||||
|
for i, level in ipairs(LEVELS) do
|
||||||
|
LEVELS[level] = i
|
||||||
|
logging[level] = level
|
||||||
|
end
|
||||||
|
|
||||||
|
local function rewrite_stacktrace()
|
||||||
|
-- prettify stack-trace, remove lualogging entries and reformat to 1 line
|
||||||
|
local result = ''
|
||||||
|
local trace = debug.traceback()
|
||||||
|
for entry in trace:gmatch("%s*(.-)\n") do
|
||||||
|
if entry:match("%:%d+%:") and not entry:find('logging.lua') then
|
||||||
|
result = result .. ' | ' .. entry
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
-- private log function, with support for formating a complex log message.
|
||||||
|
local function LOG_MSG(self, level, fmt, ...)
|
||||||
|
local f_type = type(fmt)
|
||||||
|
if f_type == 'string' then
|
||||||
|
if select('#', ...) > 0 then
|
||||||
|
local status, msg = pcall(format, fmt, ...)
|
||||||
|
if status then
|
||||||
|
return self:append(level, msg)
|
||||||
|
else
|
||||||
|
return self:append(level, "Error formatting log message: " .. msg .. rewrite_stacktrace())
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- only a single string, no formating needed.
|
||||||
|
return self:append(level, fmt)
|
||||||
|
end
|
||||||
|
elseif f_type == 'function' then
|
||||||
|
-- fmt should be a callable function which returns the message to log
|
||||||
|
return self:append(level, fmt(...))
|
||||||
|
end
|
||||||
|
-- fmt is not a string and not a function, just call tostring() on it.
|
||||||
|
return self:append(level, logging.tostring(fmt))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- do nothing function for disabled levels.
|
||||||
|
local function disable_level()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- a generic print function that prints to the log
|
||||||
|
local function print_to_log(logger, level, ...)
|
||||||
|
local args = {
|
||||||
|
n = select("#", ...),
|
||||||
|
...,
|
||||||
|
}
|
||||||
|
for i = 1, args.n do
|
||||||
|
args[i] = _tostring(args[i])
|
||||||
|
end
|
||||||
|
args = table.concat(args, " ") .. "\n"
|
||||||
|
for line in args:gmatch("(.-)\n") do
|
||||||
|
logger:log(level, line)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- improved assertion function.
|
||||||
|
local function assert(exp, ...)
|
||||||
|
-- if exp is true, we are finished so don't do any processing of the parameters
|
||||||
|
if exp then
|
||||||
|
return exp, ...
|
||||||
|
end
|
||||||
|
-- assertion failed, raise error
|
||||||
|
error(format(...), 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Creates a new logger object
|
||||||
|
-- @param append Function used by the logger to append a message with a
|
||||||
|
-- log-level to the log stream.
|
||||||
|
-- @return Table representing the new logger object.
|
||||||
|
-- @return String if there was any error setting the custom levels if provided
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
function logging.new(append)
|
||||||
|
if type(append) ~= "function" then
|
||||||
|
return nil, "Appender must be a function."
|
||||||
|
end
|
||||||
|
|
||||||
|
local LEVEL_FUNCS = {}
|
||||||
|
|
||||||
|
local logger = {}
|
||||||
|
logger.append = append
|
||||||
|
|
||||||
|
logger.setLevel = function(self, level)
|
||||||
|
local order = LEVELS[level]
|
||||||
|
assert(order, "undefined level '%s'", _tostring(level))
|
||||||
|
local old_level = self.level
|
||||||
|
self.level = level
|
||||||
|
self.level_order = order
|
||||||
|
-- enable/disable levels
|
||||||
|
for i = 1, MAX_LEVELS do
|
||||||
|
local name = LEVELS[i]:lower()
|
||||||
|
if i >= order and i ~= MAX_LEVELS then
|
||||||
|
self[name] = LEVEL_FUNCS[i]
|
||||||
|
else
|
||||||
|
self[name] = disable_level
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if old_level and old_level ~= level then
|
||||||
|
self:log(LEVELS[1], "Logger: changing loglevel from %s to %s", old_level, level)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- generic log function.
|
||||||
|
logger.log = function(self, level, ...)
|
||||||
|
local order = LEVELS[level]
|
||||||
|
assert(order, "undefined level `%s'", _tostring(level))
|
||||||
|
if order < self.level_order then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
return LOG_MSG(self, level, ...)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- a print function generator
|
||||||
|
logger.getPrint = function(self, level)
|
||||||
|
local order = LEVELS[level]
|
||||||
|
assert(order, "undefined level `%s'", _tostring(level))
|
||||||
|
return function(...)
|
||||||
|
if order >= self.level_order then
|
||||||
|
print_to_log(self, level, ...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- create the proxy functions for each log level.
|
||||||
|
for i = 1, MAX_LEVELS do
|
||||||
|
local level = LEVELS[i]
|
||||||
|
if logger[level:lower()] then
|
||||||
|
return nil, "'" .. level .. "' is not a proper level name since there is already a property '" ..
|
||||||
|
level:lower() .. "'"
|
||||||
|
end
|
||||||
|
LEVEL_FUNCS[i] = function(self, ...)
|
||||||
|
-- no level checking needed here, this function will only be called if it's level is active.
|
||||||
|
return LOG_MSG(self, level, ...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- insert log level constants
|
||||||
|
for i = 1, MAX_LEVELS do
|
||||||
|
logger[LEVELS[i]] = LEVELS[i]
|
||||||
|
end
|
||||||
|
|
||||||
|
-- initialize log level.
|
||||||
|
logger:setLevel(LEVELS[1])
|
||||||
|
return logger
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Prepares the log message
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
function logging.prepareLogMsg(pattern, dt, level, message)
|
||||||
|
local logMsg = pattern or "%date %level %message\n"
|
||||||
|
message = string.gsub(message, "%%", "%%%%")
|
||||||
|
logMsg = string.gsub(logMsg, "%%date", dt)
|
||||||
|
logMsg = string.gsub(logMsg, "%%level", level)
|
||||||
|
logMsg = string.gsub(logMsg, "%%message", message)
|
||||||
|
return logMsg
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Converts a Lua value to a string
|
||||||
|
--
|
||||||
|
-- Converts Table fields in alphabetical order
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
local function tostring(value)
|
||||||
|
local str = ''
|
||||||
|
|
||||||
|
if (type(value) ~= 'table') then
|
||||||
|
if (type(value) == 'string') then
|
||||||
|
str = string.format("%q", value)
|
||||||
|
else
|
||||||
|
str = _tostring(value)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local auxTable = {}
|
||||||
|
for key in pairs(value) do
|
||||||
|
if (tonumber(key) ~= key) then
|
||||||
|
table.insert(auxTable, key)
|
||||||
|
else
|
||||||
|
table.insert(auxTable, tostring(key))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.sort(auxTable)
|
||||||
|
|
||||||
|
str = str .. '{'
|
||||||
|
local separator = ""
|
||||||
|
local entry
|
||||||
|
for _, fieldName in ipairs(auxTable) do
|
||||||
|
if ((tonumber(fieldName)) and (tonumber(fieldName) > 0)) then
|
||||||
|
entry = tostring(value[tonumber(fieldName)])
|
||||||
|
else
|
||||||
|
entry = fieldName .. " = " .. tostring(value[fieldName])
|
||||||
|
end
|
||||||
|
str = str .. separator .. entry
|
||||||
|
separator = ", "
|
||||||
|
end
|
||||||
|
str = str .. '}'
|
||||||
|
end
|
||||||
|
return str
|
||||||
|
end
|
||||||
|
logging.tostring = tostring
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Backward compatible parameter handling
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
function logging.getDeprecatedParams(lst, ...)
|
||||||
|
local args = {
|
||||||
|
n = select("#", ...),
|
||||||
|
...,
|
||||||
|
}
|
||||||
|
if type(args[1]) == "table" then
|
||||||
|
-- this is the new format of a single params-table
|
||||||
|
return args[1]
|
||||||
|
end
|
||||||
|
|
||||||
|
local params = {}
|
||||||
|
for i, param_name in ipairs(lst) do
|
||||||
|
params[param_name] = args[i]
|
||||||
|
end
|
||||||
|
return params
|
||||||
|
end
|
||||||
|
|
||||||
|
return logging
|
||||||
@ -0,0 +1,89 @@
|
|||||||
|
---------------------------------------------------------------------------
|
||||||
|
-- RollingFileAppender is a FileAppender that rolls over the logfile
|
||||||
|
-- once it has reached a certain size limit. It also mantains a
|
||||||
|
-- maximum number of log files.
|
||||||
|
--
|
||||||
|
-- @author Tiago Cesar Katcipis (tiagokatcipis@gmail.com)
|
||||||
|
--
|
||||||
|
-- @copyright 2004-2021 Kepler Project
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
local logging = require "zlog.logging"
|
||||||
|
|
||||||
|
local buffer_mode
|
||||||
|
do
|
||||||
|
local dir_separator = _G.package.config:sub(1, 1)
|
||||||
|
local is_windows = dir_separator == '\\'
|
||||||
|
if is_windows then
|
||||||
|
-- Windows does not support "line" buffered mode, see
|
||||||
|
-- https://github.com/lunarmodules/lualogging/pull/9
|
||||||
|
buffer_mode = "no"
|
||||||
|
else
|
||||||
|
buffer_mode = "line"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function openFile(self)
|
||||||
|
self.file = io.open(self.filename, "a")
|
||||||
|
if not self.file then
|
||||||
|
return nil, string.format("file `%s' could not be opened for writing", self.filename)
|
||||||
|
end
|
||||||
|
self.file:setvbuf(buffer_mode)
|
||||||
|
return self.file
|
||||||
|
end
|
||||||
|
|
||||||
|
local rollOver = function(self)
|
||||||
|
for i = self.maxIndex - 1, 1, -1 do
|
||||||
|
-- files may not exist yet, lets ignore the possible errors.
|
||||||
|
os.rename(self.filename .. "." .. i, self.filename .. "." .. i + 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
self.file:close()
|
||||||
|
self.file = nil
|
||||||
|
|
||||||
|
local _, msg = os.rename(self.filename, self.filename .. "." .. "1")
|
||||||
|
|
||||||
|
if msg then
|
||||||
|
return nil, string.format("error %s on log rollover", msg)
|
||||||
|
end
|
||||||
|
|
||||||
|
return openFile(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
local openRollingFileLogger = function(self)
|
||||||
|
if not self.file then
|
||||||
|
return openFile(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
local filesize = self.file:seek("end", 0)
|
||||||
|
|
||||||
|
if (filesize < self.maxSize) then
|
||||||
|
return self.file
|
||||||
|
end
|
||||||
|
|
||||||
|
return rollOver(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
function logging.rolling_file(params, ...)
|
||||||
|
params = logging.getDeprecatedParams({"filename", "maxFileSize", "maxBackupIndex", "logPattern"}, params, ...)
|
||||||
|
local logPattern = params.logPattern
|
||||||
|
local timestampPattern = params.timestampPattern
|
||||||
|
|
||||||
|
local obj = {
|
||||||
|
filename = type(params.filename) == "string" and params.filename or "lualogging.log",
|
||||||
|
maxSize = params.maxFileSize,
|
||||||
|
maxIndex = params.maxBackupIndex or 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
return logging.new(function(self, level, message)
|
||||||
|
local f, msg = openRollingFileLogger(obj)
|
||||||
|
if not f then
|
||||||
|
return nil, msg
|
||||||
|
end
|
||||||
|
local s = logging.prepareLogMsg(logPattern, os.date(timestampPattern), level, message)
|
||||||
|
f:write(s)
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
return logging.rolling_file
|
||||||
|
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
local logging = require 'zlog.logging'
|
||||||
|
|
||||||
|
function logging.syslog(ident, facility)
|
||||||
|
local lsyslog = require 'lsyslog'
|
||||||
|
|
||||||
|
local convert = {
|
||||||
|
[logging.DEBUG] = lsyslog.LEVEL.DEBUG,
|
||||||
|
[logging.INFO] = lsyslog.LEVEL.INFO,
|
||||||
|
[logging.WARN] = lsyslog.LEVEL.WARNING,
|
||||||
|
[logging.ERROR] = lsyslog.LEVEL.ERR,
|
||||||
|
[logging.FATAL] = lsyslog.LEVEL.ALERT,
|
||||||
|
}
|
||||||
|
|
||||||
|
if type(ident) ~= 'string' then
|
||||||
|
ident = 'lua'
|
||||||
|
end
|
||||||
|
|
||||||
|
lsyslog.open(ident, facility or lsyslog.FACILITY.USER)
|
||||||
|
|
||||||
|
return logging.new(function(self, level, message)
|
||||||
|
lsyslog.log(convert[level] or lsyslog.LEVEL.ERR, message)
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
return logging.syslog
|
||||||
Loading…
Reference in New Issue