lua logger

This commit is contained in:
云风
2012-08-13 14:26:00 +08:00
parent 497490c74e
commit 04f9eaea49
5 changed files with 461 additions and 1 deletions

87
lualib/log.lua Normal file
View File

@@ -0,0 +1,87 @@
local Logger = require("logger")
local l = Logger:new()
l.stack_level = l.stack_level + 1
local logging = {}
logging.NOLOG = l.NOLOG
logging.DEBUG = l.DEBUG
logging.INFO = l.INFO
logging.WARNING = l.WARNING
logging.ERROR = l.ERROR
logging.CRITICAL = l.CRITICAL
logging.FATAL = l.FATAL
--
-- public interface
--
function logging.Debug(...)
l:Debug(...)
end
function logging.Debugf(format, ...)
l:Debugf(format, ...)
end
function logging.Info(...)
l:Info(...)
end
function logging.Infof(format, ...)
l:Infof(format, ...)
end
function logging.Warning(...)
l:Warning(...)
end
function logging.Warningf(format, ...)
l:Warningf(format, ...)
end
function logging.Error(...)
l:Error(...)
end
function logging.Errorf(format, ...)
l:Errorf(format, ...)
end
function logging.Critical(...)
l:Critical(...)
end
function logging.Criticalf(format, ...)
l:Criticalf(format, ...)
end
function logging.Fatal(...)
l:Fatal(...)
end
function logging.Fatalf(format, ...)
l:Fatalf(format,...)
end
function logging.Assert(v, message)
return l:Assert(v,message)
end
function logging.SError(message, level)
level = level and level+1 or 2
return l:SError(message, level)
end
function logging.Tag(key, value)
l:Tag(key,value)
end
function logging.Untag(key)
l:Untag(key)
end
function logging.set_modname(name)
l:set_modname(name)
end
function logging.config(t)
l:config(t)
end
return logging

320
lualib/logger.lua Normal file
View File

@@ -0,0 +1,320 @@
local Skynet = require("skynet")
local assert = assert
local error = error
local print = print
local tconcat = table.concat
local tinsert = table.insert
local srep = string.rep
local type = type
local pairs = pairs
local tostring = tostring
local next = next
local logger = {}
-- public field
logger.NOLOG = 0
logger.DEBUG = 10
logger.INFO = 20
logger.WARNING = 30
logger.ERROR = 40
logger.CRITICAL = 50
logger.FATAL = 60
local function log_to_disk(...)
Skynet.send(".lualog" , Skynet.pack(...))
end
local function dump_log_to_disk(t)
for i=1,#t do
log_to_disk(table.unpack(t[i]))
end
end
--
-- log helper fun
--
local function get_log_src(level)
local info = debug.getinfo(level+1, "Sl")
local src = info.source
return src .. ":" .. info.currentline .. ":"
end
local starttime = Skynet.starttime()
local function log_timestamp(timestamp)
local sec = timestamp / 100
local ms = timestamp % 100
local f = os.date("%Y-%m-%d %H:%M:%S",starttime + sec)
f = string.format("%s.%02d",f,ms)
return f
end
local function table_serialize(root)
local cache = { [root] = "." }
local function _dump(t,space,name)
local temp = {}
for k,v in pairs(t) do
local key = tostring(k)
if cache[v] then
tinsert(temp,"+" .. key .. " {" .. cache[v].."}")
elseif type(v) == "table" then
local new_key = name .. "." .. key
cache[v] = new_key
tinsert(temp,"+" .. key .. _dump(v,space .. (next(t,k) and "|" or " " ).. srep(" ",#key),new_key))
else
tinsert(temp,"+" .. key .. " [" .. tostring(v).."]")
end
end
return tconcat(temp,"\n"..space)
end
return (_dump(root, "",""))
end
local function log_format(level, ...)
local t = {...}
local out = ''
for _,v in pairs(t) do
if level <= logger.DEBUG and type(v) == "table" then
v_str = "table:" .. table_serialize(v)
else
v_str = tostring(v)
end
if out == '' then
out = v_str
else
out = out .. "\t" .. v_str
end
end
return out
end
local function tag_table_to_tags(tag_table)
if tag_table and next(tag_table) then
local tags = {}
for k,v in pairs(tag_table) do
tags[#tags + 1] = k..":"..v
end
return tags
end
end
--
-- end log helper fun
--
--
-- dump list mgr
--
local function _lnew(n)
local l = {}
l.tail = 1
l.len = n
return l
end
local function _lreset(l)
l.tail = 1
return l
end
local function _lpush(l,...)
l[l.tail] = {...}
l[l.tail - l.len] = nil
l.tail = l.tail + 1
end
local function _lempty(l)
return l.tail == 1
end
local function _lrange(l)
if l.tail <= l.len then
return 1, l.tail-1
end
return l.tail - l.len, l.tail-1
end
--
-- end dump list mgr
--
function logger:cache(...)
_lpush(self.dump_list,...)
end
-- 构造符合 lualog 次序的 message, 由 pack_log_message 使用
function logger:get_log_message(level, timestamp, src, ...)
local msg = log_format(level, ...)
local modname = self.module_name or self.default_module_name
local name = self.logger_name or modname
local timestamp = log_timestamp(timestamp)
return name, modname, level, timestamp,msg, src, tags
end
function logger:dump()
if _lempty(self.dump_list) then
return
end
local head, tail = _lrange(self.dump_list)
local log_message_list = {}
for i= head,tail do
log_message_list[#log_message_list + 1] = {self:get_log_message(table.unpack(self.dump_list[i]))}
end
dump_log_to_disk(log_message_list)
_lreset(self.dump_list)
end
function logger:log_i(...)
log_to_disk(self:get_log_message(...))
end
function logger:log(level, ...)
-- 过滤掉信息的条件未设置dump_level且level低于log_level
if self.dump_level == logger.NOLOG and level < self.log_level then
return
end
local timestamp = Skynet.now()
local src = self.log_src and get_log_src(self.stack_level) or ''
if level < self.log_level then -- 低于记录级别, 缓存
self:cache(level, timestamp, src, ...)
else
self:log_i(level, timestamp, src, ...) -- 低于dump级别直接记录
if self.dump_level ~= logger.NOLOG and level >= self.dump_level then -- dump缓存
self:dump()
end
end
end
--
-- public interface
--
function logger:Debug(...)
self:log(logger.DEBUG, ...)
end
function logger:Debugf(format, ...)
self:log(logger.DEBUG, string.format(format, ...))
end
function logger:Info(...)
self:log(logger.INFO, ...)
end
function logger:Infof(format, ...)
self:log(logger.INFO, string.format(format, ...))
end
function logger:Warning(...)
self:log(logger.WARNING, ...)
end
function logger:Warningf(format, ...)
self:log(logger.WARNING, string.format(format,...))
end
function logger:Error(...)
self:log(logger.ERROR, ...)
end
function logger:Errorf(format, ...)
self:log(logger.ERROR, string.format(format,...))
end
function logger:Critical(...)
self:log(logger.CRITICAL, ...)
end
function logger:Criticalf(format, ...)
self:log(logger.CRITICAL, string.format(format,...))
end
function logger:Fatal(...)
self:log(logger.FATAL, ...)
end
function logger:Fatalf(format, ...)
self:log(logger.FATAL, string.format(format,...))
end
function logger:Assert(v, message)
if not v then
self:log(logger.ERROR, "assert:"..tostring(message))
end
return assert(v, message)
end
function logger:SError(message, level)
level = level and level+1 or 2
self:log(logger.CRITICAL, "error:" .. tostring(message))
error(message, level)
end
function logger:Tag(key, value)
self.tag_table[key] = value
self.tags = tag_table_to_tags(tag_table)
end
function logger:Untag(key)
self.tag_table[key]=nil
self.tags = tag_table_to_tags(self.tag_table)
end
function logger:set_modname(name)
self.module_name = name
end
function logger:config(t)
if t["name"] ~= nil then
self.logger_name = t["name"]
end
if t["module_name"] ~= nil then
self.module_name = t["module_name"]
end
if t["to_screen"] ~= nil then
self.to_screen = t["to_screen"]
end
if t["level"] ~= nil then
self.log_level = t["level"]
end
if t["log_src"] ~= nil then
self.log_src = t["log_src"]
end
if t["dump_level"] ~= nil then
self.dump_level = t["dump_level"]
end
if self.dump_level ~= logger.NOLOG then
assert(self.dump_level > self.log_level)
end
end
function logger:new()
-- private field
local obj = {}
obj.default_module_name = "skynet"
obj.logger_name = nil
obj.module_name = nil
obj.to_screen = true
obj.log_level = logger.DEBUG
obj.log_src = true
obj.dump_level = logger.NOLOG
obj.dump_num = 100
self.dump_list = _lnew(obj.dump_num)
obj.tag_table = {}
obj.tags = nil
obj.stack_level = 3
setmetatable(obj, logger)
logger.__index = logger
return obj
end
return logger

44
service/lualog.lua Normal file
View File

@@ -0,0 +1,44 @@
local skynet = require "skynet"
local log_level_desc = {
[0] = "NOLOG",
[10] = "DEBUG",
[20] = "INFO",
[30] = "WARNING",
[40] = "ERROR",
[50] = "CRITICAL",
[60] = "FATAL",
}
--
-- log object
--
function log_format(self)
if self.tags and next(self.tags) then
return string.format("[%s %s *%s*] [%s]%s %s", self.timestamp,self.level,self.name,table.concat(self.tags, ","),self.src,self.msg)
else
return string.format("[%s %s *%s*]%s %s", self.timestamp,self.level,self.name,self.src,self.msg)
end
end
--
-- end log object
--
local function log(name, modname, level, timestamp, msg, src, tags)
print(log_format {
name = name,
modname = modname,
level = log_level_desc[level],
timestamp = timestamp,
msg = msg,
src = src or '',
tags = tags,
})
end
skynet.dispatch(function(msg, sz , session , from)
log(skynet.unpack(msg,sz))
end)
skynet.register ".lualog"

View File

@@ -4,6 +4,8 @@ skynet.dispatch()
skynet.start(function() skynet.start(function()
print("Server start") print("Server start")
local lualog = skynet.launch("snlua","lualog")
print("lualog",lualog)
local launcher = skynet.launch("snlua","launcher") local launcher = skynet.launch("snlua","launcher")
print("launcher", launcher) print("launcher", launcher)
local console = skynet.launch("snlua","console") local console = skynet.launch("snlua","console")
@@ -17,4 +19,4 @@ skynet.start(function()
local redis = skynet.call(".launcher", "broker .redis snlua redis-cli 127.0.0.1:6379") local redis = skynet.call(".launcher", "broker .redis snlua redis-cli 127.0.0.1:6379")
print("redis",redis) print("redis",redis)
skynet.exit() skynet.exit()
end) end)

7
service/testlog.lua Normal file
View File

@@ -0,0 +1,7 @@
local skynet = require "skynet"
local log = require "log"
skynet.dispatch()
log.Info("hello world")