mirror of
https://github.com/pound-emu/ballistic.git
synced 2026-10-24 23:45:05 -07:00
129 lines
2.6 KiB
Lua
129 lines
2.6 KiB
Lua
-- Usage:
|
|
-- package.path = package.path .. ";path-to-this-file"
|
|
-- local log = require("log")
|
|
-- log.info("Engine initialized.")
|
|
-- log.error("Failed: %s (%d)", reason, code)
|
|
|
|
local M = {}
|
|
|
|
M.levels = {
|
|
NONE = -1,
|
|
ERROR = 0,
|
|
WARN = 1,
|
|
INFO = 2,
|
|
DEBUG = 3,
|
|
TRACE = 4,
|
|
}
|
|
|
|
local level_names = {
|
|
[-1] = "NONE",
|
|
[0] = "ERROR",
|
|
[1] = "WARN",
|
|
[2] = "INFO",
|
|
[3] = "DEBUG",
|
|
[4] = "TRACE",
|
|
}
|
|
|
|
M.min_level = M.levels.TRACE
|
|
|
|
local function normalize_level(level)
|
|
if type(level) == "string" then
|
|
local n = M.levels[level:upper()]
|
|
|
|
if n == nil then
|
|
error("invalid log level: " .. level, 3)
|
|
end
|
|
|
|
return n
|
|
end
|
|
|
|
if type(level) ~= "number" or level ~= math.floor(level) then
|
|
error("log level must be integer or level name", 3)
|
|
end
|
|
|
|
if level < M.levels.NONE or level > M.levels.TRACE then
|
|
error("invalid log level: " .. tostring(level), 3)
|
|
end
|
|
|
|
return level
|
|
end
|
|
|
|
local function clean_source(source)
|
|
if type(source) ~= "string" then
|
|
return "=[?]"
|
|
end
|
|
|
|
if source:sub(1, 1) == "@" then
|
|
source = source:sub(2)
|
|
end
|
|
|
|
local base = source:match(".*[/\\](.*)$")
|
|
return base or source
|
|
end
|
|
|
|
local function caller_name(info)
|
|
if info.name and info.name ~= "" then
|
|
return info.name
|
|
end
|
|
|
|
if info.what == "main" then
|
|
return "main"
|
|
end
|
|
|
|
if info.what == "C" then
|
|
return "C"
|
|
end
|
|
|
|
return "anonymous"
|
|
end
|
|
|
|
local function format_message(message, ...)
|
|
if select("#", ...) == 0 then
|
|
return tostring(message)
|
|
end
|
|
|
|
local ok, formatted = pcall(string.format, tostring(message), ...)
|
|
|
|
if ok then
|
|
return formatted
|
|
end
|
|
|
|
return tostring(message)
|
|
end
|
|
|
|
local function emit(level, message, ...)
|
|
if level == M.levels.NONE or level > M.min_level then
|
|
return
|
|
end
|
|
|
|
local info = debug.getinfo(3, "Snl") or {}
|
|
local level_str = level_names[level] or "MISSING"
|
|
local func = caller_name(info)
|
|
local filename = clean_source(info.source)
|
|
local line = info.currentline or -1
|
|
local text = format_message(message, ...)
|
|
io.stderr:write(string.format("[%s] [%s] [%s:%d] %s\n",
|
|
level_str, func, filename, line, text))
|
|
end
|
|
|
|
function M.log(level, message, ...)
|
|
emit(normalize_level(level), message, ...)
|
|
end
|
|
|
|
function M.error(message, ...) emit(M.levels.ERROR, message, ...) end
|
|
function M.warn(message, ...) emit(M.levels.WARN, message, ...) end
|
|
function M.info(message, ...) emit(M.levels.INFO, message, ...) end
|
|
function M.debug(message, ...) emit(M.levels.DEBUG, message, ...) end
|
|
function M.trace(message, ...) emit(M.levels.TRACE, message, ...) end
|
|
|
|
function M.set_level(level)
|
|
M.min_level = normalize_level(level)
|
|
end
|
|
|
|
M.ERROR = M.error
|
|
M.WARN = M.warn
|
|
M.INFO = M.info
|
|
M.DEBUG = M.debug
|
|
M.TRACE = M.trace
|
|
|
|
return M |