Created
July 8, 2015 08:22
-
-
Save marcotrosi/1a150a36e900b15602ca to your computer and use it in GitHub Desktop.
Lua - automatic logging idea
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- load the log module | |
local log = require("log") | |
-- some function for demo | |
function add(a, b) | |
return a+b | |
end | |
-- wrap the main script in a main function | |
function main() | |
add(128, 293 ) | |
add(227, "43.23") -- internal conversion works | |
add(227, "43,23") -- internal conversion fails -> program crashes | |
add(983, 123 ) -- never reached | |
end | |
-- register functions for logging | |
log.Functions = | |
{ | |
["add"] = true, | |
} | |
-- initialize the logging | |
log.initLog() | |
-- call main func and writeLog in case of failure | |
xpcall(main, log.writeLog) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
log = {} | |
function convertTableToString_s(t) -- <<< | |
local ret_t = {} | |
local function convertTableToStringHelper(obj, cnt) | |
local cnt=cnt or 0 | |
if type(obj) == "table" then | |
table.insert(ret_t, "\n" .. string.rep("\t",cnt) .. "{\n") | |
cnt = cnt+1 | |
for k,v in pairs(obj) do | |
if type(k) == "string" then | |
table.insert(ret_t, string.rep("\t",cnt) .. '["' .. k .. '"] = ') | |
end | |
if type(k) == "number" then | |
table.insert(ret_t, string.rep("\t",cnt) .. "[" .. k.. "] = ") | |
end | |
convertTableToStringHelper(v, cnt) | |
table.insert(ret_t, ",\n") | |
end | |
cnt = cnt-1 | |
table.insert(ret_t, string.rep("\t",cnt) .. "}") | |
elseif type(obj) == "string" then | |
table.insert(ret_t, string.format("%q",obj)) | |
else | |
table.insert(ret_t, tostring(obj)) | |
end | |
end | |
convertTableToStringHelper(t) | |
return table.concat(ret_t) | |
end -- >>> | |
-- TODO check how to handle functions as parameter ? | |
-- TODO check how to handle elipse ... (nameless parameters) ? | |
function log.log(Event_s) -- <<< | |
Info_t = debug.getinfo(2, "n") | |
Function_s = Info_t.name | |
if log.Functions[Function_s] then | |
local Data = {Function=Function_s, Event=Event_s} | |
local UpValueCnt_n = 1 | |
local UpValues_t = {} | |
while true do | |
Name, Value = debug.getlocal(2, UpValueCnt_n) | |
if (Event_s == "call") and (Name == '(*temporary)') then | |
break | |
end | |
if (Name == nil) then | |
break | |
end | |
if type(Value) == "string" then | |
table.insert(UpValues_t, {["Name"]=Name, ["Type"]="string", ["Value"]=string.format("%q", Value)}) | |
end | |
if type(Value) == "number" then | |
table.insert(UpValues_t, {["Name"]=Name, ["Type"]="number", ["Value"]=tostring(Value)}) | |
end | |
if type(Value) == "nil" then | |
table.insert(UpValues_t, {["Name"]=Name, ["Type"]="nil" , ["Value"]=tostring(Value)}) | |
end | |
if type(Value) == "table" then | |
table.insert(UpValues_t, {["Name"]=Name, ["Type"]="table" , ["Value"]=convertTableToString_s(Value)}) | |
end | |
UpValueCnt_n = UpValueCnt_n + 1 | |
end | |
if (Event_s == "return") then | |
table.remove(UpValues_t) -- remove last entry, it's a Lua internal | |
end | |
Data.UpValues = UpValues_t | |
table.insert(log.Data, Data) | |
if (table.maxn(log.Data) > (log.Max or 20)) and (log.Max ~= 0) then | |
table.remove(log.Data, 1) | |
end | |
end | |
end -- >>> | |
function log.writeLog() -- <<< | |
if log.IsOn ~= true then | |
return | |
end | |
local LogFile_h = io.open(log.File, "w+") | |
if LogFile_h then | |
for i,v in ipairs(log.Data or {}) do | |
LogFile_h:write(v.Event .. " " .. v.Function,"\n") | |
for _,p in ipairs(v.UpValues) do | |
LogFile_h:write(" "..p.Name.." "..p.Type.." "..p.Value.."\n") | |
end | |
LogFile_h:write("────────────────────────────────────────────────\n") | |
end | |
LogFile_h:write(string.format("Time Stamp: %s\n" , os.date())) | |
LogFile_h:write(string.format("Lua Version: %s\n", _VERSION )) | |
--LogFile_h:write(string.format("Operating System: %s\n", (os.getenv("OSTYPE") or "windows") )) -- does not work. OSTYPE is available on my system but somehow I get nil here | |
LogFile:close() | |
else | |
io.stderr:write("\nlog error: could not open '"..log.File.."' for writing\n") | |
end | |
end -- >>> | |
function log.initLog() -- <<< | |
if log.IsOn == true then | |
debug.sethook(log.log, "cr") -- c and/or r | |
log.Data = {} | |
end | |
end -- >>> | |
-- default values for log <<< | |
log.IsOn = true -- logging on/off | |
log.File = "./logfile.log" -- name of the log file | |
log.Max = 20 -- maximum number of log entries, set to 0 to log everything, default is 20 | |
-- >>> | |
return log | |
-- vim: fmr=<<<,>>> fdm=marker |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
call add | |
a number 128 | |
b number 293 | |
──────────────────────────────────────────────── | |
return add | |
a number 128 | |
b number 293 | |
(*temporary) number 421 | |
──────────────────────────────────────────────── | |
call add | |
a number 227 | |
b string "43.23" | |
──────────────────────────────────────────────── | |
return add | |
a number 227 | |
b string "43.23" | |
(*temporary) number 270.23 | |
──────────────────────────────────────────────── | |
call add | |
a number 227 | |
b string "43,23" | |
──────────────────────────────────────────────── | |
Time Stamp: Wed Jul 8 10:17:04 2015 | |
Lua Version: Lua 5.2 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment