🐳 chore(库): 增加 日志库

develop
xiaojin 5 years ago
parent 50453c05f3
commit 674f932099

@ -16,6 +16,7 @@ globals = {
"instanceof", "instanceof",
"mixin", "mixin",
"handler", "handler",
"fmt",
"Property", "Property",
"Enum", "Enum",
"Option", "Option",

@ -4,8 +4,15 @@ https://github.com/Tencent/secguide
本地 dns 系统: 本地 dns 系统:
https://github.com/mafintosh/dns-discovery https://github.com/mafintosh/dns-discovery
100个gdb小技巧
https://github.com/hellogcc/100-gdb-tips
Modern Unix Command
https://github.com/ibraheemdev/modern-unix
https://github.com/cloudwu/skynet/issues/288 https://github.com/cloudwu/skynet/issues/288
启动服务器流程要理清楚(架构图) 启动服务器流程要理清楚(架构图)
凡是 道具生成都是 一套 掉落系统 凡是 道具生成都是 一套 掉落系统

@ -12,6 +12,7 @@ LFLAGS = $(SHARED) -I$(SKYNET_LUA_INC)
LUA_CLIB_PATH ?= ../luaclib LUA_CLIB_PATH ?= ../luaclib
##################################################### #####################################################
LFS_SO = $(LUA_CLIB_PATH)/lfs.so LFS_SO = $(LUA_CLIB_PATH)/lfs.so
CJSON_SO = $(LUA_CLIB_PATH)/cjson.so CJSON_SO = $(LUA_CLIB_PATH)/cjson.so
PROFILE_SO = $(LUA_CLIB_PATH)/profile.so PROFILE_SO = $(LUA_CLIB_PATH)/profile.so
@ -27,6 +28,7 @@ TERMFX_SO = $(LUA_CLIB_PATH)/termfx.so
RC4_SO = $(LUA_CLIB_PATH)/rc4.so RC4_SO = $(LUA_CLIB_PATH)/rc4.so
MATH_SO = $(LUA_CLIB_PATH)/math3d.so MATH_SO = $(LUA_CLIB_PATH)/math3d.so
CFFI_SO = $(LUA_CLIB_PATH)/cffi.so CFFI_SO = $(LUA_CLIB_PATH)/cffi.so
LSYSLOG_SO = $(LUA_CLIB_PATH)/lsyslog.so
##################################################### #####################################################
@ -44,6 +46,7 @@ all: $(LFS_SO) \
$(CLUA_SO) \ $(CLUA_SO) \
$(MATH_SO) \ $(MATH_SO) \
$(CFFI_SO) \ $(CFFI_SO) \
$(LSYSLOG_SO) \
$(LUASOCKET_SO) $(LUASOCKET_SO)
##################################################### #####################################################
@ -84,6 +87,9 @@ $(MATH_SO):
$(CFFI_SO): $(CFFI_SO):
cd ../3rd/ffi-lua && $(MAKE) PLAT=$(PLAT) cd ../3rd/ffi-lua && $(MAKE) PLAT=$(PLAT)
$(LSYSLOG_SO):
cd lua-syslog && $(MAKE) PLAT=$(PLAT)
$(RC4_SO): $(RC4_SO):
cd lua-rc4 && $(MAKE) PLAT=$(PLAT) cd lua-rc4 && $(MAKE) PLAT=$(PLAT)

@ -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;
}

@ -40,13 +40,13 @@ print("skipset", skipset)
local math3d = require "math3d" local math3d = require "math3d"
print("math3d", math3d) print("math3d", math3d)
local fmt = require "fmt"
print("fmt", fmt)
local ffi = require("cffi") local ffi = require("cffi")
if ffi.abi("64bit") then if ffi.abi("64bit") then
assert(ffi.sizeof("void *") == 8) assert(ffi.sizeof("void *") == 8)
elseif ffi.abi("32bit") then elseif ffi.abi("32bit") then
assert(ffi.sizeof("void *") == 4) assert(ffi.sizeof("void *") == 4)
end end
print("ffi", ffi) print("ffi", ffi)
local syslog = require 'lsyslog'
print("syslog", syslog)

@ -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

@ -3,6 +3,7 @@ require "oop.mixin"
require "oop.property" require "oop.property"
require "oop.enum" require "oop.enum"
fmt = require "oop.fstrings"
handler = require "oop.handler" handler = require "oop.handler"
Option = require "oop.option" Option = require "oop.option"
Try = require "oop.try" Try = require "oop.try"

@ -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…
Cancel
Save