这个log库是从github上的开源框架中看到的,发现其挺好用,就单独摘出来,作为单独的模块。
该作者的github地址为:https://github.com/xiaozia/metoo
输出的日志格式方便自定义,比如是下面这样:
[INFO] 2020-07-13 05:40:22 [main] [./demo/main.lua:10] start main info test...
[ERROR] 2020-07-13 05:40:22 [main] [./demo/main.lua:11] start main error test...
这个方便写流水日志
一、编译log.so
大家可以把这个开源库clone下来
https://github.com/xiaozia/metoo.git
把lua-log.c单独复制出来,在其相同目录下新建一个makfile文件:
(文章的最后,我会这个demo的文件的下载地址放上来)
CC ?= gcc
CFLAGS = -g -O2 -Wall -I$(LUA_INC)
SHARED := -fPIC --shared
TARGET = log.so
LUA_CLIB_PATH = ./
#引入lua头文件(根据你安装Lua库时的目录而定)
LUA_INC ?= /home/moon/Documents/skynet_project/3rd/lua
start: $(TARGET)
$(TARGET) : ./lua-log.c
$(CC) $(CFLAGS) $(SHARED) $^ -o $@
clean:
rm -fr $(TARGET)
$(LUA_CLIB_PATH) :
mkdir $(LUA_CLIB_PATH)
其中LUA_INC ?=
这里的路径可以填skynet中lua的路径
make
就会看到生成了一个log.so,如果有报错,或者想更详细了解如何用C语言作为skynet的模块,可以看这篇博客:
Skynet服务器框架(七) Lua中调用自定义C库
二、自定义的流水日志服务
log.lua
local skynet = require "skynet"
require "skynet.manager"
local logger = require "log.core"
local CMD = {}
function CMD.start()
logger.init(tonumber(skynet.getenv("log_level")) or 0,
tonumber(skynet.getenv("log_rollsize")) or 1024,
tonumber(skynet.getenv("log_flushinterval")) or 5,
skynet.getenv("log_dirname") or "log",
skynet.getenv("log_basename") or "test")
end
function CMD.stop( )
logger.exit()
end
function CMD.debug(name, msg)
logger.debug(string.format("%s [%s] %s",os.date("%Y-%m-%d %H:%M:%S"), name, msg))
end
function CMD.info(name, msg)
logger.info(string.format("%s [%s] %s",os.date("%Y-%m-%d %H:%M:%S"), name, msg))
end
function CMD.warning(name, msg)
logger.warning(string.format("%s [%s] %s",os.date("%Y-%m-%d %H:%M:%S"), name, msg))
end
function CMD.error(name, msg)
logger.error(string.format("%s [%s] %s",os.date("%Y-%m-%d %H:%M:%S"), name, msg))
end
function CMD.fatal(name, msg)
logger.fatal(string.format("%s [%s] %s",os.date("%Y-%m-%d %H:%M:%S"), name, msg))
end
skynet.start(function()
skynet.dispatch("lua", function(session, source, cmd, ...)
local f = assert(CMD[cmd], cmd .. "not found")
if cmd == "start" or cmd == "stop" then
skynet.retpack(f(...))
else
f(...)
end
end)
skynet.register(SERVICE_NAME)
end)
再定义一个log_helper.lua
local skynet = require "skynet"
local M = {}
function M.LOG_DEBUG(fmt, ...)
local msg = string.format(fmt, ...)
local info = debug.getinfo(2)
if info then
msg = string.format("[%s:%d] %s", info.short_src, info.currentline, msg)
end
skynet.send("log", "lua", "debug", SERVICE_NAME, msg)
end
function M.LOG_INFO(fmt, ...)
local msg = string.format(fmt, ...)
local info = debug.getinfo(2)
if info then
msg = string.format("[%s:%d] %s", info.short_src, info.currentline, msg)
end
skynet.send("log", "lua", "info", SERVICE_NAME, msg)
end
function M.LOG_WARNING(fmt, ...)
local msg = string.format(fmt, ...)
local info = debug.getinfo(2)
if info then
msg = string.format("[%s:%d] %s", info.short_src, info.currentline, msg)
end
skynet.send("log", "lua", "warning", SERVICE_NAME, msg)
end
function M.LOG_ERROR(fmt, ...)
local msg = string.format(fmt, ...)
local info = debug.getinfo(2)
if info then
msg = string.format("[%s:%d] %s", info.short_src, info.currentline, msg)
end
skynet.send("log", "lua", "error", SERVICE_NAME, msg)
end
function M.LOG_FATAL(fmt, ...)
local msg = string.format(fmt, ...)
local info = debug.getinfo(2)
if info then
msg = string.format("[%s:%d] %s", info.short_src, info.currentline, msg)
end
skynet.send("log", "lua", "fatal", SERVICE_NAME, msg)
end
return M
三、参数说明
在log.lua文件中我们看到:
function CMD.start()
logger.init(tonumber(skynet.getenv("log_level")) or 0,
tonumber(skynet.getenv("log_rollsize")) or 1024,
tonumber(skynet.getenv("log_flushinterval")) or 5,
skynet.getenv("log_dirname") or "log",
skynet.getenv("log_basename") or "test")
end
这些参数是留给我们配置的。
log_level 是日志级别,和这个枚举对应
enum logger_level
{
DEBUG = 0,
INFO = 1,
WARNING = 2,
ERROR = 3,
FATAL = 4
};
日志级别默认是0,即DEBUG
log_rollsize 日志文件达该大小就滚动一个新文件,单位是MB,默认是1024,即默认日志文件1GB就自动创建一个新的日志文件
log_flushinterval 是日志同步到磁盘间隔时间,默认是5秒;
log_basename 是日志文件的前缀,log_test.20200713-0.log
我写的log_basename是log_test 那么刚才看到的前缀就是这个log_basename
log_dirname是目录名,是相对目录,比如我写成log,它就自动创建该文件夹,并将日志文件放到这里,该参数是存放日志的目录名
四、测试
将第一步中生成的log.so放到skynet可以找到的位置,比如在lua_cpath中添加路径,或者直接放到luaclib文件夹中。
刚才的两个lua文件,log.lua是lua服务文件,需要放到skynet可以找到的lua服务路径中,而log_helper.lua只是普通的lua文件,只需要将其路径添加到lua_path中。
main.lua
local skynet = require "skynet"
local log_helper = require "log_helper"
skynet.start(function()
skynet.error("=======Server start=======")
local log = skynet.uniqueservice("log")
skynet.call(log, "lua", "start")
log_helper.LOG_INFO("start main info test...")
log_helper.LOG_ERROR("start main error test...")
skynet.exit()
end)
conf中的参数:
log_dirname = "log"
log_basename = "log_test"
运行结果:
[INFO] 2020-07-13 05:40:22 [main] [./demo/main.lua:10] start main info test...
[ERROR] 2020-07-13 05:40:22 [main] [./demo/main.lua:11] start main error test...
五、全部代码
全部的代码我打包放到这里:
链接:https://pan.baidu.com/s/17wTACI-SJ309kuUyMLrolQ
提取码:ejyo