🐳 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