[Skynet 基础】(二) 创建日志服务

本文介绍了如何使用Lua定制Skynet的日志服务,包括基本配置和使用Lua脚本自定义日志级别、输出格式以及文件管理。
摘要由CSDN通过智能技术生成

概述

日志模块主要用于格式化输出程序日志,方便后续从日志中定位程序运行过程中出现的问题。当然日志除了日志内容本身之外,还应该包括文件名、行号、时间戳、线程、协程号、日志级别等信息。在输出错误日志时,还应附加程序的函数调用栈信息,便于后续分析和排查问题。

日志系统一般分为 5 个等级

  • DEBUG :调试用的日志,线上运行时屏蔽不输出
  • INFO :普通日志,线上运行时输出,流程的关键步骤都需要有 INFO 日志
  • WARN :数据异常,但不影响正常流程的时候输出
  • ERROR :数据异常,且需要人工处理的时候输出
  • FATAL :致命错误, 将会导致应用程序的退出。

基本配置

-- config
logger = "./skynet.log" 			--日志输出的目录文件
logservice = "logger"				--默认为 “logger” 如果配置 "snlua "可使用Lua定制日志服务

使用Lua定制日志服务

: 修改自 Veinin/skynet-logger

-- config
logger = "logger" 					--日志输出的目录文件
logservice = "snlua"				--默认为 “logger” 如果配置 "snlua "可使用Lua定制日志服务
logpath = "./log/"					--日志存放的目录路径
loggroup   = "test"   -- 日志文件分组名
-- lualib/log.lua
local skynet = require "skynet"

local log = {}

local LOG_LEVEL = {
    DEBUG   = 1,
    INFO    = 2, 
    WARN    = 3, 
    ERROR   = 4, 
    FATAL   = 5
}

local OUT_PUT_LEVEL = LOG_LEVEL.DEBUG

local LOG_LEVEL_DESC = {
    [1] = "DEBUG",
    [2] = "INFO",
    [3] = "WARN",
    [4] = "ERROR",
    [5] = "FATAL",
}

local function format(fmt, ...)
    local ok, str = pcall(string.format, fmt, ...)
    if ok then
        return str
    else
        return "error format : " .. fmt
    end
end

local function send_log(level, ...)
    if level < OUT_PUT_LEVEL then
        return
    end

    local str
    if select("#", ...) == 1 then
        str = tostring(...)
    else
        str = format(...)
    end

    local info = debug.getinfo(3)
	if info then
		local filename = string.match(info.short_src, "[^/.]+.lua$")
		str = string.format("[%s:%d] %s", filename, info.currentline, str)
    end
    
    skynet.send(".logger", "lua", "logging", LOG_LEVEL_DESC[level], str)
end

function log.debug(fmt, ...)
    send_log(LOG_LEVEL.DEBUG, fmt, ...)
end

function log.info(fmt, ...)
    send_log(LOG_LEVEL.INFO, fmt, ...)
end

function log.warn(fmt, ...)
    send_log(LOG_LEVEL.WARN, fmt, ...)
end

function log.error(fmt, ...)
    send_log(LOG_LEVEL.ERROR, fmt, ...)
end

function log.fatal(fmt, ...)
    send_log(LOG_LEVEL.FATAL, fmt, ...)
end

return log

-- service/logger.lua
local skynet = require "skynet"
require "skynet.manager"

local last_hour	= -1
local log_path  = skynet.getenv("logpath")
local log_file  = nil
local log_group = skynet.getenv("loggroup")
local is_daemon = skynet.getenv("daemon") ~= nil

local function check_exists(path)
	if not os.rename(path, path) then
		os.execute("mkdir " .. path)
	end
end

local function file_path(date)
	if log_group ~= nil then
		return string.format("%s%s_%04d-%02d-%02d-%02d.log", log_path, log_group, 
			date.year, date.month, date.day, date.hour)
	else
		return string.format("%s%04d-%02d-%02d-%02d.log", log_path, 
			date.year, date.month, date.day, date.hour)	
	end	
end

local function open_file(date)
	check_exists(log_path)

	if log_file then
		log_file:close()
		log_file = nil
	end

	local f, e = io.open(file_path(date), "a")
	if not f then
		print("logger error:", tostring(e))
		return
	end

	log_file = f
	last_hour = date.hour
end

local function log_time(date)
	return string.format("%02d:%02d:%02d.%02d", date.hour, date.min, date.sec, 
		math.floor(skynet.time()*100%100))
end

local CMD = {}

function CMD.logging(source, type, str)
	local date = os.date("*t")
	str = string.format("[:%08x][%s][%s]%s", source, type, log_time(date), str)
	
	if not log_file or date.hour ~= last_hour then
		open_file(date)
	end

	log_file:write(str .. '\n')
	log_file:flush()
	
	if not is_daemon then
		print(str)
	end
end

skynet.register_protocol {
	name = "text",
	id = skynet.PTYPE_TEXT,
	unpack = skynet.tostring,
	dispatch = function(_, source, msg)
		CMD.logging(source, "DEBUG", msg)
	end
}

skynet.register_protocol {
	name = "SYSTEM",
	id = skynet.PTYPE_SYSTEM,
	unpack = function(...) return ... end,
	dispatch = function(_, source)
		-- reopen signal
		print("SIGHUP")
		CMD.logging(source, "FATAL", "SIGHUP")
	end
}

skynet.start(function()
	skynet.register(".logger")
	
    skynet.dispatch("lua", function(_, source, cmd, ...)
		local f = assert(CMD[cmd], cmd .. " not found")
		f(source, ...)
	end)
end)

-- service/main.lua
local skynet = require "skynet"
local log = require "log"

skynet.start(function()
  --初始化
  log.debug("Value of Pi = %f", math.pi)
  log.debug("Value of Pi = 3.14159")
  log.debug("debug")
  log.info("info")
  log.warn("warn")
  log.error("error")
  log.fatal("fatal")
  --退出自身
  skynet.exit()
end)

最后打印日志结果
每行日志信息为:[服务ID][日志等级][日志输出时间(精确到毫秒级别)][日志输出文件名:文件行数] 日志内容,如下面一行行日志信息:
在这里插入图片描述

  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值