You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

213 lines
4.9 KiB
Lua

local skynet = require "skynet"
local log_define = require "zlog.log_define"
local queue = require "skynet.queue"
require "skynet.manager"
local LOG_LEVEL = log_define.LOG_LEVEL
local DEFAULT_CATEGORY = log_define.DEFAULT_CATEGORY
local log_format = log_define.format
local color = log_define.color
local string_match = string.match
local skynet_env = require("skynet.env")
local nodeid = skynet_env.get("nodeid")
local zenv = require("zenv.init")
local define = zenv.Logger
local log_root = define.log_root
local log_level = define.log_level or LOG_LEVEL.INFO
local log_console = define.log_console
local name = zenv.get_node_conf(nodeid).name
local log_prefix = name .. "_"
local last_day = -1
local category = ...
local is_master = not category
local category_addr = {}
local lock = queue()
local file
local function close_file()
if not file then
return
end
file:close()
file = nil
end
local function open_file(date)
date = date or os.date("*t")
local dir = log_define.log_dir(log_root, date)
if not os.rename(dir, dir) then
os.execute("mkdir -p " .. dir)
end
if file then
close_file()
end
local path = log_define.log_path(dir, log_prefix, category, date)
local f, e = io.open(path, "a")
if not f then
print("logger error:", tostring(e))
return
end
file = f
last_day = date.day
end
local CMD = {}
function CMD.console(level, msg)
print(color(level, msg))
end
function CMD.log(level, msg)
if level < log_level then
return
end
msg = msg or ""
local date = os.date("*t")
if not file or date.day ~= last_day then
open_file(date)
end
file:write(msg .. '\n')
file:flush()
if log_console then
if is_master then
CMD.console(level, msg)
else
skynet.call(".logger", "lua", "console", level, msg)
end
end
end
function CMD.set_console(is_open)
log_console = is_open
if is_master then
for _, addr in pairs(category_addr) do
skynet.call(addr, "lua", "set_console", is_open)
end
end
end
function CMD.set_level(level)
log_level = level
if is_master then
for _, addr in pairs(category_addr) do
skynet.call(addr, "lua", "set_level", level)
end
end
end
function CMD.get_service(cate)
if not is_master then
return
end
local addr
lock(function()
addr = category_addr[cate]
if not addr then
addr = skynet.newservice("logger", cate)
category_addr[cate] = addr
end
end)
return addr
end
if is_master then
skynet.info_func(function()
return {
log_console = log_console,
log_level = log_level,
}
end)
skynet.register_protocol {
name = "text",
id = skynet.PTYPE_TEXT,
unpack = skynet.tostring,
dispatch = function(_, addr, msg)
local level = LOG_LEVEL.INFO
if string_match(msg, "maybe in an endless loop") then
level = LOG_LEVEL.WARN
end
if string_match(msg, "stack traceback:") then
level = LOG_LEVEL.ERROR
end
msg = log_format(addr, level, nil, msg)
CMD.log(level, msg)
end,
}
local SIGHUP_CMD = {}
local function get_first_line(filename)
local f = io.open(filename, "r")
if not f then
return
end
local first_line = f:read("l")
f:close()
return first_line
end
local function get_sighup_cmd(sighup_file)
local cmd = get_first_line(sighup_file)
if not cmd then
return
end
return SIGHUP_CMD[cmd]
end
local sighup_file = "./.sighup_file"
-- 捕捉sighup信号(kill -1)
skynet.register_protocol {
name = "SYSTEM",
id = skynet.PTYPE_SYSTEM,
unpack = function(...)
return ...
end,
dispatch = function(_, addr)
-- https://blog.hanxi.cc/p/75/
local cmd = get_sighup_cmd(sighup_file)
if cmd then
cmd = cmd:match("^%s*(.-)%s*$")
local func = SIGHUP_CMD[cmd]
if func then
func()
else
skynet.error(
string.format("unknow sighup cmd, need set sighup file. sighup_file: '%s'", sighup_file))
end
else
local level = LOG_LEVEL.FATAL
local msg = log_format(addr, level, nil, "SIGHUP")
CMD.log(level, msg)
end
end,
}
category_addr[DEFAULT_CATEGORY] = skynet.self()
skynet.register(".logger")
end
open_file()
skynet.start(function()
skynet.dispatch("lua", function(_, _, cmd, ...)
local f = CMD[cmd]
assert(f, cmd)
return skynet.retpack(f(...))
end)
end)