工程提交
This commit is contained in:
789
4G/tools/resource/soc_script/v2025.12.31.22/lib/exmtn.lua
Normal file
789
4G/tools/resource/soc_script/v2025.12.31.22/lib/exmtn.lua
Normal file
@@ -0,0 +1,789 @@
|
||||
--[[
|
||||
@module exmtn
|
||||
@summary 运维日志扩展库,负责日志的持久化存储
|
||||
@version 1.0
|
||||
@date 2025.12.9
|
||||
@author zengeshuai
|
||||
@usage
|
||||
exmtn.init(1, 0) -- 初始化,1个块,缓存写入
|
||||
exmtn.log("info", "tag", "message", 123) -- 输出运维日志
|
||||
]]
|
||||
|
||||
local exmtn = {}
|
||||
|
||||
-- 常量定义
|
||||
local LOG_MTN_CACHE_SIZE = 4096
|
||||
local LOG_MTN_FILE_COUNT = 4
|
||||
local LOG_MTN_CONFIG_FILE = "/exmtn.trc"
|
||||
local LOG_MTN_DEFAULT_BLOCKS_DIVISOR = 40
|
||||
local LOG_MTN_ADD_WRITE_THRESHOLD = 256
|
||||
local LOG_MTN_CONFIG_VERSION = 1
|
||||
|
||||
-- 写入方式常量
|
||||
exmtn.CACHE_WRITE = 0
|
||||
exmtn.ADD_WRITE = 1
|
||||
|
||||
-- 内部状态
|
||||
local ctx = {
|
||||
inited = false,
|
||||
enabled = false,
|
||||
cur_index = 1, -- 1-4
|
||||
block_size = 4096, -- 默认块大小
|
||||
blocks_per_file = 1, -- 每文件块数
|
||||
file_limit = 4096, -- 每文件大小限制
|
||||
write_way = 0, -- 0=缓存写入, 1=直接追加
|
||||
cache = "", -- 缓存缓冲区
|
||||
cache_used = 0, -- 缓存已使用字节数
|
||||
}
|
||||
|
||||
-- 重置缓存
|
||||
local function reset_cache()
|
||||
ctx.cache = ""
|
||||
ctx.cache_used = 0
|
||||
end
|
||||
|
||||
-- 获取当前文件路径
|
||||
local function get_file_path(index)
|
||||
return string.format("/hzmtn%d.trc", index or ctx.cur_index)
|
||||
end
|
||||
|
||||
-- 获取当前文件大小
|
||||
local function get_current_file_size()
|
||||
local path = get_file_path()
|
||||
local file = io.open(path, "rb")
|
||||
if not file then
|
||||
return 0
|
||||
end
|
||||
local size = file:seek("end")
|
||||
file:close()
|
||||
-- file:seek("end") 返回文件大小,如果失败返回 nil
|
||||
if size and size > 0 then
|
||||
return size
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
-- 检查文件是否存在
|
||||
local function file_exists(path)
|
||||
local file = io.open(path, "rb")
|
||||
if file then
|
||||
file:close()
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- 检查所有日志文件是否存在
|
||||
local function files_exist()
|
||||
for i = 1, LOG_MTN_FILE_COUNT do
|
||||
local path = get_file_path(i)
|
||||
if file_exists(path) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- 删除所有日志文件
|
||||
local function remove_files()
|
||||
for i = 1, LOG_MTN_FILE_COUNT do
|
||||
local path = get_file_path(i)
|
||||
os.remove(path)
|
||||
end
|
||||
end
|
||||
|
||||
-- 创建空文件
|
||||
local function create_files()
|
||||
for i = 1, LOG_MTN_FILE_COUNT do
|
||||
local path = get_file_path(i)
|
||||
local file = io.open(path, "wb")
|
||||
if file then
|
||||
file:close()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- 读取配置文件
|
||||
local function load_config()
|
||||
local file = io.open(LOG_MTN_CONFIG_FILE, "rb")
|
||||
if not file then
|
||||
return nil -- 文件不存在,返回 nil
|
||||
end
|
||||
|
||||
local content = file:read("*a")
|
||||
file:close()
|
||||
|
||||
if not content or #content == 0 then
|
||||
return nil -- 文件为空
|
||||
end
|
||||
|
||||
-- 解析配置:格式为 "VERSION=1\nINDEX=2\nBLOCKS=10\nWRITE_WAY=0\n"
|
||||
local config = {}
|
||||
for line in content:gmatch("[^\r\n]+") do
|
||||
-- 移除首尾空白字符
|
||||
line = line:match("^%s*(.-)%s*$") or line
|
||||
local key, value = line:match("([^=]+)=(.+)")
|
||||
if key and value then
|
||||
-- 移除 key 和 value 的首尾空白字符
|
||||
key = key:match("^%s*(.-)%s*$") or key
|
||||
value = value:match("^%s*(.-)%s*$") or value
|
||||
local num_value = tonumber(value)
|
||||
if num_value then
|
||||
config[key] = num_value
|
||||
else
|
||||
config[key] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- 验证版本号
|
||||
if config.VERSION ~= LOG_MTN_CONFIG_VERSION then
|
||||
return nil -- 版本不匹配
|
||||
end
|
||||
|
||||
return config
|
||||
end
|
||||
|
||||
-- 保存配置文件
|
||||
local function save_config(index, blocks, write_way)
|
||||
local content = string.format("VERSION=%d\nINDEX=%d\nBLOCKS=%d\nWRITE_WAY=%d\n",
|
||||
LOG_MTN_CONFIG_VERSION, index, blocks, write_way)
|
||||
|
||||
local file = io.open(LOG_MTN_CONFIG_FILE, "wb")
|
||||
if not file then
|
||||
log.warn("exmtn", "无法打开配置文件: " .. LOG_MTN_CONFIG_FILE)
|
||||
return false
|
||||
end
|
||||
|
||||
local ok = file:write(content)
|
||||
file:close()
|
||||
|
||||
if not ok then
|
||||
log.warn("exmtn", "写入配置文件失败: " .. LOG_MTN_CONFIG_FILE)
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- 更新索引(同时保存完整配置)
|
||||
local function update_index(index)
|
||||
return save_config(index, ctx.blocks_per_file, ctx.write_way)
|
||||
end
|
||||
|
||||
-- 格式化时间戳
|
||||
-- 返回格式: [2025-11-05 15:06:49.947][00000027.994]
|
||||
local function format_timestamp()
|
||||
-- 获取系统运行时间(毫秒)
|
||||
local ticks_ms = 0
|
||||
if mcu and mcu.ticks then
|
||||
local ticks = mcu.ticks()
|
||||
if ticks then
|
||||
ticks_ms = ticks
|
||||
end
|
||||
end
|
||||
|
||||
-- 获取当前日期时间
|
||||
local date_time_str = ""
|
||||
local ms = 0
|
||||
|
||||
if os and os.date then
|
||||
-- 获取当前日期时间字符串: 2025-11-05 15:06:49
|
||||
local dt = os.date("%Y-%m-%d %H:%M:%S")
|
||||
if dt then
|
||||
-- 计算毫秒:使用系统运行时间的毫秒部分
|
||||
-- 如果 RTC 已设置,时间会更准确
|
||||
ms = ticks_ms % 1000
|
||||
date_time_str = string.format("%s.%03d", dt, ms)
|
||||
end
|
||||
end
|
||||
|
||||
-- 如果无法获取日期时间,使用默认格式
|
||||
if date_time_str == "" then
|
||||
date_time_str = "1970-01-01 00:00:00.000"
|
||||
end
|
||||
|
||||
-- 计算系统运行时间(秒.毫秒)
|
||||
local uptime_sec = math.floor(ticks_ms / 1000)
|
||||
local uptime_ms = ticks_ms % 1000
|
||||
|
||||
-- 格式化运行时间部分: 00000027.994(固定宽度,9位整数+3位小数)
|
||||
local uptime_str = string.format("%09d.%03d", uptime_sec, uptime_ms)
|
||||
|
||||
-- 返回完整时间戳
|
||||
return string.format("[%s][%s]", date_time_str, uptime_str)
|
||||
end
|
||||
|
||||
-- 格式化调试信息
|
||||
local function format_debug_info(level, include_level)
|
||||
local info = debug.getinfo(2, "Sl")
|
||||
if not info or not info.source then
|
||||
return nil
|
||||
end
|
||||
|
||||
local src = info.source
|
||||
-- 跳过第一个字符(@ 或 =)
|
||||
if src:sub(1, 1) == "@" or src:sub(1, 1) == "=" then
|
||||
src = src:sub(2)
|
||||
end
|
||||
|
||||
local line = info.currentline or 0
|
||||
if line > 64 * 1024 then
|
||||
line = 0
|
||||
end
|
||||
|
||||
if include_level and level then
|
||||
return string.format("%s/%s:%d", level, src, line)
|
||||
else
|
||||
return string.format("%s:%d", src, line)
|
||||
end
|
||||
end
|
||||
|
||||
-- 格式化消息(与 log.info/warn/error 格式一致,但添加时间戳前缀)
|
||||
local function format_message(level, tag, ...)
|
||||
local argc = select("#", ...)
|
||||
|
||||
-- 获取 log.style 配置
|
||||
local log_style = 0
|
||||
if log and log.style then
|
||||
log_style = log.style() or 0
|
||||
end
|
||||
|
||||
-- 根据级别确定日志标识
|
||||
local level_char = "I" -- 默认 info
|
||||
if level == "warn" then
|
||||
level_char = "W"
|
||||
elseif level == "error" then
|
||||
level_char = "E"
|
||||
end
|
||||
|
||||
local msg = ""
|
||||
local dbg_info_with_level = format_debug_info(level_char, true)
|
||||
local dbg_info_only = format_debug_info(nil, false)
|
||||
|
||||
if log_style == 0 then
|
||||
-- LOG_STYLE_NORMAL: "I/user.tag arg1 arg2 ...\n"
|
||||
msg = string.format("%s/user.%s", level_char, tag)
|
||||
for i = 1, argc do
|
||||
local arg = select(i, ...)
|
||||
msg = msg .. " " .. tostring(arg)
|
||||
end
|
||||
elseif log_style == 1 then
|
||||
-- LOG_STYLE_DEBUG_INFO: "I/file.lua:123 tag arg1 arg2 ...\n"
|
||||
if dbg_info_with_level then
|
||||
msg = dbg_info_with_level
|
||||
else
|
||||
msg = level_char
|
||||
end
|
||||
msg = msg .. " " .. tag
|
||||
for i = 1, argc do
|
||||
local arg = select(i, ...)
|
||||
msg = msg .. " " .. tostring(arg)
|
||||
end
|
||||
else
|
||||
-- LOG_STYLE_FULL: "I/user.tag file.lua:123 arg1 arg2 ...\n"
|
||||
msg = string.format("%s/user.%s", level_char, tag)
|
||||
if dbg_info_only then
|
||||
msg = msg .. " " .. dbg_info_only
|
||||
end
|
||||
for i = 1, argc do
|
||||
local arg = select(i, ...)
|
||||
msg = msg .. " " .. tostring(arg)
|
||||
end
|
||||
end
|
||||
|
||||
msg = msg .. "\n"
|
||||
|
||||
-- 添加时间戳前缀
|
||||
local timestamp = format_timestamp()
|
||||
return timestamp .. " " .. msg
|
||||
end
|
||||
|
||||
-- 刷新缓存到文件
|
||||
local function flush_cache()
|
||||
if ctx.cache_used == 0 then
|
||||
return true
|
||||
end
|
||||
|
||||
local path = get_file_path()
|
||||
local file = io.open(path, "ab")
|
||||
if not file then
|
||||
log.warn("exmtn", "无法打开文件: " .. path)
|
||||
return false
|
||||
end
|
||||
|
||||
-- file:write 返回 true/false 或 nil,不返回字节数
|
||||
local ok = file:write(ctx.cache)
|
||||
file:close()
|
||||
|
||||
if not ok then
|
||||
log.warn("exmtn", "写入文件失败: " .. path)
|
||||
return false
|
||||
end
|
||||
|
||||
reset_cache()
|
||||
return true
|
||||
end
|
||||
|
||||
-- 直接写入文件(ADD_WRITE 模式)
|
||||
local function direct_write(data)
|
||||
local path = get_file_path()
|
||||
local file = io.open(path, "ab")
|
||||
if not file then
|
||||
log.warn("exmtn", "无法打开文件: " .. path)
|
||||
return false
|
||||
end
|
||||
|
||||
-- file:write 返回 true/false 或 nil,不返回字节数
|
||||
local ok = file:write(data)
|
||||
file:close()
|
||||
|
||||
if not ok then
|
||||
log.warn("exmtn", "写入文件失败: " .. path)
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- 将数据追加到缓存或直接写入
|
||||
local function buffer_append(data)
|
||||
if not data or #data == 0 then
|
||||
return true
|
||||
end
|
||||
|
||||
local len = #data
|
||||
|
||||
-- ADD_WRITE 模式:直接写入文件
|
||||
if ctx.write_way == exmtn.ADD_WRITE then
|
||||
-- 小数据先缓存,累积到阈值再写入
|
||||
if len < LOG_MTN_ADD_WRITE_THRESHOLD then
|
||||
if ctx.cache_used + len > LOG_MTN_CACHE_SIZE then
|
||||
if not flush_cache() then
|
||||
return false
|
||||
end
|
||||
end
|
||||
ctx.cache = ctx.cache .. data
|
||||
ctx.cache_used = ctx.cache_used + len
|
||||
-- 如果累积到阈值,立即写入
|
||||
if ctx.cache_used >= LOG_MTN_ADD_WRITE_THRESHOLD then
|
||||
return flush_cache()
|
||||
end
|
||||
return true
|
||||
end
|
||||
-- 大数据直接写入
|
||||
return direct_write(data)
|
||||
end
|
||||
|
||||
-- CACHE_WRITE 模式:原有逻辑
|
||||
if len > LOG_MTN_CACHE_SIZE then
|
||||
-- 先刷新缓存
|
||||
if not flush_cache() then
|
||||
return false
|
||||
end
|
||||
-- 大数据直接写入
|
||||
return direct_write(data)
|
||||
end
|
||||
|
||||
-- 检查缓存是否足够
|
||||
if ctx.cache_used + len > LOG_MTN_CACHE_SIZE then
|
||||
if not flush_cache() then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
ctx.cache = ctx.cache .. data
|
||||
ctx.cache_used = ctx.cache_used + len
|
||||
return true
|
||||
end
|
||||
|
||||
-- 写入日志到文件
|
||||
local function write_to_file(msg)
|
||||
if not ctx.enabled then
|
||||
return true -- 未启用时返回成功,不写入
|
||||
end
|
||||
|
||||
local len = #msg
|
||||
|
||||
-- CACHE_WRITE 模式
|
||||
if ctx.write_way == exmtn.CACHE_WRITE then
|
||||
-- 检查文件大小 + 缓存大小 + 当前数据是否会超过限制
|
||||
-- 如果会超过,先刷新缓存
|
||||
if ctx.cache_used > 0 then
|
||||
local file_sz = get_current_file_size()
|
||||
if file_sz + ctx.cache_used + len > ctx.file_limit then
|
||||
-- 先刷新缓存
|
||||
if not flush_cache() then
|
||||
return false
|
||||
end
|
||||
-- 重新获取文件大小
|
||||
file_sz = get_current_file_size()
|
||||
-- 检查文件是否已满
|
||||
if file_sz >= ctx.file_limit then
|
||||
-- 文件已满,切换到下一个文件
|
||||
ctx.cur_index = (ctx.cur_index % LOG_MTN_FILE_COUNT) + 1
|
||||
local path = get_file_path()
|
||||
local file = io.open(path, "wb")
|
||||
if file then
|
||||
file:close()
|
||||
end
|
||||
if not update_index(ctx.cur_index) then
|
||||
log.warn("exmtn", "更新索引失败")
|
||||
return false
|
||||
end
|
||||
reset_cache()
|
||||
end
|
||||
end
|
||||
else
|
||||
-- 缓存为空,检查文件大小
|
||||
local file_sz = get_current_file_size()
|
||||
if file_sz + len > ctx.file_limit then
|
||||
-- 文件已满,切换到下一个文件
|
||||
ctx.cur_index = (ctx.cur_index % LOG_MTN_FILE_COUNT) + 1
|
||||
local path = get_file_path()
|
||||
local file = io.open(path, "wb")
|
||||
if file then
|
||||
file:close()
|
||||
end
|
||||
if not update_index(ctx.cur_index) then
|
||||
log.warn("exmtn", "更新索引失败")
|
||||
return false
|
||||
end
|
||||
reset_cache()
|
||||
end
|
||||
end
|
||||
|
||||
-- 如果加入这条数据后缓存会满,先刷新缓存
|
||||
if ctx.cache_used + len > LOG_MTN_CACHE_SIZE then
|
||||
if not flush_cache() then
|
||||
return false
|
||||
end
|
||||
|
||||
-- 刷新后再次检查文件大小
|
||||
local file_sz = get_current_file_size()
|
||||
if file_sz >= ctx.file_limit then
|
||||
-- 文件已满,切换到下一个文件
|
||||
ctx.cur_index = (ctx.cur_index % LOG_MTN_FILE_COUNT) + 1
|
||||
local path = get_file_path()
|
||||
local file = io.open(path, "wb")
|
||||
if file then
|
||||
file:close()
|
||||
end
|
||||
if not update_index(ctx.cur_index) then
|
||||
log.warn("exmtn", "更新索引失败")
|
||||
return false
|
||||
end
|
||||
reset_cache()
|
||||
end
|
||||
end
|
||||
|
||||
-- 加入缓存
|
||||
return buffer_append(msg)
|
||||
else
|
||||
-- ADD_WRITE 模式:先刷新缓存,确保文件大小准确
|
||||
if ctx.cache_used > 0 then
|
||||
if not flush_cache() then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- 获取当前文件大小
|
||||
local file_sz = get_current_file_size()
|
||||
|
||||
-- 检查当前文件是否已写满
|
||||
if file_sz >= ctx.file_limit then
|
||||
-- 文件已满,切换到下一个文件
|
||||
ctx.cur_index = (ctx.cur_index % LOG_MTN_FILE_COUNT) + 1
|
||||
local path = get_file_path()
|
||||
local file = io.open(path, "wb")
|
||||
if file then
|
||||
file:close()
|
||||
end
|
||||
if not update_index(ctx.cur_index) then
|
||||
log.warn("exmtn", "更新索引失败")
|
||||
return false
|
||||
end
|
||||
reset_cache()
|
||||
end
|
||||
|
||||
-- 检查当前数据是否能放入当前文件
|
||||
if file_sz + len > ctx.file_limit then
|
||||
-- 当前数据放不下,切换到下一个文件
|
||||
ctx.cur_index = (ctx.cur_index % LOG_MTN_FILE_COUNT) + 1
|
||||
local path = get_file_path()
|
||||
local file = io.open(path, "wb")
|
||||
if file then
|
||||
file:close()
|
||||
end
|
||||
if not update_index(ctx.cur_index) then
|
||||
log.warn("exmtn", "更新索引失败")
|
||||
return false
|
||||
end
|
||||
reset_cache()
|
||||
end
|
||||
|
||||
-- 加入缓存或直接写入(buffer_append 会根据大小决定)
|
||||
return buffer_append(msg)
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
初始化运维日志
|
||||
@api exmtn.init(blocks, write_way)
|
||||
@int blocks 每个文件的块数,0表示禁用,正整数表示块数量
|
||||
@int write_way 写入方式,可选参数。exmtn.CACHE_WRITE(0)表示缓存写入,exmtn.ADD_WRITE(1)表示直接追加写入,默认为exmtn.CACHE_WRITE
|
||||
@return boolean 成功返回true,失败返回false
|
||||
@usage
|
||||
exmtn.init(1, exmtn.CACHE_WRITE) -- 初始化,1个块,缓存写入
|
||||
]]
|
||||
function exmtn.init(blocks, write_way)
|
||||
-- 参数校验
|
||||
if blocks == nil then
|
||||
blocks = 0
|
||||
end
|
||||
blocks = math.floor(blocks)
|
||||
if blocks < 0 then
|
||||
log.warn("exmtn", "无效的块数")
|
||||
return false
|
||||
end
|
||||
|
||||
write_way = write_way or exmtn.CACHE_WRITE
|
||||
if write_way ~= exmtn.CACHE_WRITE and write_way ~= exmtn.ADD_WRITE then
|
||||
write_way = exmtn.CACHE_WRITE
|
||||
end
|
||||
|
||||
-- 如果禁用
|
||||
if blocks == 0 then
|
||||
reset_cache()
|
||||
remove_files()
|
||||
ctx.enabled = false
|
||||
ctx.cur_index = 1
|
||||
-- 删除配置文件
|
||||
os.remove(LOG_MTN_CONFIG_FILE)
|
||||
ctx.inited = true
|
||||
return true
|
||||
end
|
||||
|
||||
-- 读取文件系统信息
|
||||
if not ctx.inited then
|
||||
ctx.block_size = 4096
|
||||
ctx.blocks_per_file = 1
|
||||
|
||||
-- 尝试获取文件系统信息(需要 fs 模块支持)
|
||||
-- fs.fsstat 返回: success, total_blocks, used_blocks, block_size, fs_type
|
||||
if fs and fs.fsstat then
|
||||
local success, total_blocks, used_blocks, block_size, fs_type = fs.fsstat("/")
|
||||
if success and block_size and block_size > 0 then
|
||||
ctx.block_size = block_size
|
||||
if total_blocks and total_blocks > 0 then
|
||||
local def_blocks = math.floor(total_blocks / LOG_MTN_DEFAULT_BLOCKS_DIVISOR)
|
||||
if def_blocks > 0 then
|
||||
ctx.blocks_per_file = def_blocks
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- 读取配置文件(仅在首次初始化时读取)
|
||||
if not ctx.inited then
|
||||
local config = load_config()
|
||||
if config then
|
||||
-- 读取索引
|
||||
if config.INDEX and config.INDEX >= 1 and config.INDEX <= LOG_MTN_FILE_COUNT then
|
||||
ctx.cur_index = config.INDEX
|
||||
end
|
||||
|
||||
-- 读取块数配置
|
||||
if config.BLOCKS and config.BLOCKS > 0 then
|
||||
ctx.blocks_per_file = config.BLOCKS
|
||||
end
|
||||
|
||||
-- 读取写入方式配置
|
||||
if config.WRITE_WAY == 0 or config.WRITE_WAY == 1 then
|
||||
ctx.write_way = config.WRITE_WAY
|
||||
end
|
||||
|
||||
log.info("exmtn", "读取索引", ctx.cur_index)
|
||||
log.info("exmtn", "读取块数配置", ctx.blocks_per_file)
|
||||
log.info("exmtn", "读取写入方式配置", ctx.write_way)
|
||||
end
|
||||
end
|
||||
|
||||
-- 检查配置是否变化
|
||||
-- 如果已初始化,比较当前配置和新配置;如果未初始化,不需要判断(首次初始化总是"变化"的)
|
||||
local config_changed = false
|
||||
if ctx.inited then
|
||||
-- 已初始化:比较当前配置和新传入的配置
|
||||
config_changed = (ctx.blocks_per_file ~= blocks) or (ctx.write_way ~= write_way)
|
||||
end
|
||||
-- 未初始化:config_changed 保持为 false,因为首次初始化不算"变化"
|
||||
|
||||
log.info("exmtn", "配置变化", config_changed)
|
||||
-- 更新配置
|
||||
ctx.blocks_per_file = blocks
|
||||
ctx.write_way = write_way
|
||||
ctx.file_limit = ctx.block_size * ctx.blocks_per_file
|
||||
if ctx.file_limit == 0 then
|
||||
ctx.file_limit = LOG_MTN_CACHE_SIZE
|
||||
end
|
||||
|
||||
-- 处理文件的三种情况
|
||||
if config_changed then
|
||||
-- 情况1:配置变化,清空文件
|
||||
log.info("exmtn", "配置变化,清空文件")
|
||||
reset_cache()
|
||||
remove_files()
|
||||
create_files()
|
||||
ctx.cur_index = 1
|
||||
elseif files_exist() then
|
||||
-- 情况2:配置没有变化,文件存在,根据配置文件中保存的文件指针继续写
|
||||
log.info("exmtn", "配置未变化,文件存在,继续写入")
|
||||
-- ctx.cur_index 已经从配置文件读取(如果是首次初始化)或保持当前值(如果已初始化),不需要重置
|
||||
else
|
||||
-- 情况3:配置没有变化,文件不存在,创建文件
|
||||
log.info("exmtn", "配置未变化,文件不存在,创建文件")
|
||||
create_files()
|
||||
-- ctx.cur_index 已经从配置文件读取(如果是首次初始化)或保持当前值(如果已初始化),不需要重置
|
||||
end
|
||||
|
||||
-- 保存配置到文件
|
||||
if not save_config(ctx.cur_index, blocks, write_way) then
|
||||
log.warn("exmtn", "保存配置失败")
|
||||
return false
|
||||
end
|
||||
|
||||
ctx.enabled = true
|
||||
ctx.inited = true
|
||||
|
||||
-- 打印初始化信息
|
||||
if blocks > 0 then
|
||||
local total_size = ctx.file_limit * LOG_MTN_FILE_COUNT
|
||||
local file_size_mb = ctx.file_limit / (1024 * 1024)
|
||||
local total_size_mb = total_size / (1024 * 1024)
|
||||
local file_size_kb = ctx.file_limit / 1024
|
||||
local total_size_kb = total_size / 1024
|
||||
|
||||
if ctx.file_limit >= 1024 * 1024 then
|
||||
log.info("exmtn", string.format("初始化成功: 每个文件 %.2f MB (%d 块 × %d 字节), 总空间 %.2f MB (%d 个文件)",
|
||||
file_size_mb, ctx.blocks_per_file, ctx.block_size, total_size_mb, LOG_MTN_FILE_COUNT))
|
||||
elseif ctx.file_limit >= 1024 then
|
||||
log.info("exmtn", string.format("初始化成功: 每个文件 %.2f KB (%d 块 × %d 字节), 总空间 %.2f KB (%d 个文件)",
|
||||
file_size_kb, ctx.blocks_per_file, ctx.block_size, total_size_kb, LOG_MTN_FILE_COUNT))
|
||||
else
|
||||
log.info("exmtn", string.format("初始化成功: 每个文件 %d 字节 (%d 块 × %d 字节), 总空间 %d 字节 (%d 个文件)",
|
||||
ctx.file_limit, ctx.blocks_per_file, ctx.block_size, total_size, LOG_MTN_FILE_COUNT))
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
--[[
|
||||
输出运维日志并写入文件
|
||||
@api exmtn.log(level, tag, ...)
|
||||
@string level 日志级别,必须是 "info", "warn", 或 "error"
|
||||
@string tag 日志标识,必须是字符串
|
||||
@... 需打印的参数
|
||||
@return boolean 成功返回true,失败返回false
|
||||
@usage
|
||||
exmtn.log("info", "message", 123)
|
||||
exmtn.log("warn", "message", 456)
|
||||
exmtn.log("error", "message", 789)
|
||||
]]
|
||||
function exmtn.log(level, tag, ...)
|
||||
if not level or type(level) ~= "string" then
|
||||
log.warn("exmtn", "level 必须是字符串")
|
||||
return false
|
||||
end
|
||||
|
||||
if not tag or type(tag) ~= "string" then
|
||||
log.warn("exmtn", "tag 必须是字符串")
|
||||
return false
|
||||
end
|
||||
|
||||
-- 根据级别调用对应的底层函数(会被日志级别过滤)
|
||||
if level == "info" then
|
||||
log.info(tag, ...)
|
||||
elseif level == "warn" then
|
||||
log.warn(tag, ...)
|
||||
elseif level == "error" then
|
||||
log.error(tag, ...)
|
||||
else
|
||||
log.warn("exmtn", "level 必须是 'info', 'warn' 或 'error'")
|
||||
return false
|
||||
end
|
||||
|
||||
-- 格式化消息(用于文件写入)
|
||||
local msg = format_message(level, tag, ...)
|
||||
if not msg then
|
||||
log.warn("exmtn", "格式化消息失败")
|
||||
return false
|
||||
end
|
||||
|
||||
-- 写入文件(不受日志级别影响)
|
||||
return write_to_file(msg)
|
||||
end
|
||||
|
||||
--[[
|
||||
获取当前配置
|
||||
@api exmtn.get_config()
|
||||
@return table|nil 配置信息,失败返回nil
|
||||
@usage
|
||||
local config = exmtn.get_config()
|
||||
if config then
|
||||
log.info("exmtn", "blocks:", config.blocks, "write_way:", config.write_way)
|
||||
end
|
||||
]]
|
||||
function exmtn.get_config()
|
||||
if not ctx.inited then
|
||||
return nil
|
||||
end
|
||||
return {
|
||||
enabled = ctx.enabled,
|
||||
cur_index = ctx.cur_index,
|
||||
block_size = ctx.block_size,
|
||||
blocks_per_file = ctx.blocks_per_file,
|
||||
file_limit = ctx.file_limit,
|
||||
write_way = ctx.write_way,
|
||||
}
|
||||
end
|
||||
|
||||
--[[
|
||||
清除所有运维日志文件
|
||||
@api exmtn.clear()
|
||||
@return boolean 成功返回true,失败返回false
|
||||
@usage
|
||||
local ok = exmtn.clear()
|
||||
if ok then
|
||||
log.info("exmtn", "日志文件已清除")
|
||||
end
|
||||
]]
|
||||
function exmtn.clear()
|
||||
-- 如果已初始化,先刷新缓存(确保数据不丢失)
|
||||
if ctx.inited and ctx.cache_used > 0 then
|
||||
if not flush_cache() then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- 删除所有日志文件
|
||||
remove_files()
|
||||
|
||||
-- 重新创建空文件
|
||||
create_files()
|
||||
|
||||
-- 重置索引为1
|
||||
ctx.cur_index = 1
|
||||
|
||||
-- 更新配置文件
|
||||
if not save_config(1, ctx.blocks_per_file, ctx.write_way) then
|
||||
return false
|
||||
end
|
||||
|
||||
log.info("exmtn", "运维日志文件已清除")
|
||||
return true
|
||||
end
|
||||
|
||||
return exmtn
|
||||
|
||||
Reference in New Issue
Block a user