Aaron Suen fdce76e605 More fine-grained control of logtrace
Allow watchers to subscribe to only specific event
levels (or higher) instead of having only firehose mode
or nothing.
2023-06-12 20:34:17 -04:00

92 lines
2.5 KiB
Lua

-- LUALOCALS < ---------------------------------------------------------
local ipairs, minetest, pairs, rawset, string, table, tonumber, type
= ipairs, minetest, pairs, rawset, string, table, tonumber, type
local string_sub, table_concat
= string.sub, table.concat
-- LUALOCALS > ---------------------------------------------------------
minetest.register_privilege("logtrace", "Receive server log messages")
local levels = {"all", "verbose", "info", "action", "warning", "error", "none"}
local levelidx = {}
for i, v in ipairs(levels) do levelidx[v] = i end
-- unambiguous aliases
do
local pend = {}
for k, v in pairs(levelidx) do
for len = 1, #k do
local hits = 0
for k2 in pairs(levelidx) do
if string_sub(k, 1, len) == string_sub(k2, 1, len) then
hits = hits + 1
end
end
if hits == 1 then
pend[string_sub(k, 1, len)] = v
end
end
end
for k, v in pairs(pend) do levelidx[k] = v end
end
local function getlevel(player)
return tonumber(player:get_meta():get_string("logtrace") or "") or levelidx.none
end
minetest.register_chatcommand("logtrace", {
description = "Get/set debug trace message level",
privs = {logtrace = true},
params = "[" .. table_concat(levels, "|") .. "]",
func = function(name, param)
local player = minetest.get_player_by_name(name)
if not player then return end
if (not param) or (param == "") then
local old = getlevel(player)
return true, "log trace level: " .. (
tonumber(old) and levels[old] or old)
end
local lv = levelidx[param]
if not lv then
return false, "invalid log trace level, must be one of "
.. table_concat(levels, ", ")
end
player:get_meta():set_string("logtrace",
lv == levelidx.none and "" or lv)
return true, "log trace level set to " .. levels[lv]
end,
})
local started
minetest.after(0, function() started = true end)
local function logtrace(...)
local t = {"#", ...}
for i, v in ipairs(t) do
if type(v) == "table" then
t[i] = minetest.serialize(v):sub(("return "):length())
end
end
local pref = t[2] or "all"
local msglv = levelidx[pref] or levelidx.all
local msg = table_concat(t, " ")
for _, p in pairs(minetest.get_connected_players()) do
local n = p:get_player_name()
if minetest.get_player_privs(n).logtrace then
local lv = getlevel(p)
if msglv >= lv then
minetest.chat_send_player(n, msg)
end
end
end
end
local function tracify(func)
return function(...)
if started then logtrace(...) end
return func(...)
end
end
rawset(_G, "print", tracify(print))
minetest.log = tracify(minetest.log)