Logger in LSLua Thread last updated on 2006-12-10 20:32:02

Posted by member 12025 on 2006-12-09 23:17:49

It's not terribly polished, but it works, and I documented it. :)

The main purpose is that sometimes I'll get infinite loops, stack overflows, or just odd xLabel behavior in scripts that end up as messy as fractal's before they really work (I'm just a perfectionist, so I rewrite them nicely in the end ;)). So, log certain points to find where it's been going wrong.

Just do a
require "log"


--[[ SEE BOTTOM FOR DOCS/LICENSING ]]

require "evar"

local io = io;
local evar = evar;
local type = type;
local exec = lslua.exec;
local exec = lslua.exec;
local find = string.find;
local gsub = string.gsub;
local getformat = string.format;
local tostring = tostring;
local pairs = pairs;
local ipairs = ipairs;
local ins = table.insert;
local rem = table.remove;
local os = os;
local date = os.date;
local lslua = lslua;
local milli = lslua.milli;
local string = string;

module "log"

-- is the logger even going to to run?
enable_logging = false;

-- how many lines before the log is flushed out to the hard drive?
flushlimit = 50;

-- new log for each flush?
-- if not, one log file is replaced each time
flushtonewlog = true;

-- how many log files should there be (maximum)?
-- Only valid if flushtonewlog is true.
maxlogs = 5;

-- where should the log be written to?
path = evar.miscdir;

-- log name/prefix (prefix if flushtonew is set)
logname = "log for ";

-- how should the date be formatted?
getdate = function ()
local t = date ("*t")
--[[ t = {
hour 14
min 36
wday 1
year 2003
yday 124
month 5
sec 33
day 4
isdst true (is daylight savings time)
} ]]

return t["hour"]..":"..t["min"].."."..t["sec"]
end;

-- hex color codes for gumdropping
colors = {
error = { -- purples
"c000cc", "8D0096", "5E0064"
},
warning = { -- reds
"C00000", "A00000", "800000"
},
info = { -- blues
"0000C0", "000080", "000060"
},
text = {
"000000", "404040", "808080"
},
numcolors = 3 -- number per table
};

--names in log for each tag
alt = {
error = "error",
warning = "warning",
info = "note"
}

-- don't mess with these unless you're editing the module!
logs = {}; -- paths to current logs

log = {} -- tables: { time = "", source = "", tag = "", text = "" }

error = function (s,t)
ins ( log, {
time = getdate (),
tag = "error",
source = s,
text = t } )
checkforflush ()
end;

warn = function (s,t)
ins ( log, {
time = getdate (),
tag = "warning",
source = s,
text = t } )
checkforflush ()
end;

warning = warn;

info = function (s,t)
ins ( log, {
time = getdate (),
tag = "info",
source = s,
text = t } )
checkforflush ()
end;

checkforflush = function ()
if #log == flushlimit then
flush ()
end
end;

flush = function ()
local f = logname
if flushtonewlog == true then
local t = date ("*t")
f = f..t['year']..string.format ("%.2i",t['month'])..string.format ("%.2i",t['day']).." "..string.format ("%.2i",t['hour']).."."..string.format ("%.2i",t['min']).."."..string.format ("%.2i",t['sec']).." ("..string.format ("%.3i",milli())..")"
end

local content = ""..f.."\n\n\n\n"
content = content.."TIMETYPESOURCEMESSAGE"
local warnings = 1
local errors = 1
local infos = 1
local tagcolor = ""
local textcolor = ""
local numc = colors.numcolors

for i,v in ipairs (log) do
if v.tag == "info" then
infos = infos+1
tagcolor = colors.info[infos%numc+1]
elseif v.tag == "error" then
errors = errors+1
tagcolor = colors.error[errors%numc+1]
else
warnings = warnings+1
tagcolor = colors.warning[warnings%numc+1]
end
textcolor = colors.text[(i-1)%numc+1]

content = content.."\n\t"
content = content.."\n\t\t"..(v.time)..""
content = content.."\n\t\t"..(v.tag)..""
content = content.."\n\t\t"..(v.source)..""
content = content.."\n\t\t"..(v.text)..""
content = content.."\n\t"
end
--lslua.message_box (content)

content = content.."\n\n"

local file = io.open (path..f..".html", "w")
file:write (content)
file:close ()
if flushtonewlog then
ins (logs, f..".html")
checklogs ()
end
log = {}
end;

checklogs = function ()
if #logs > maxlogs then
os.remove (path..logs[1])
rem (logs,1)
end
end

-- disable/enable logging.
logfunctions = {
warn = warn,
error = error,
info = info
}
function toggle (b)
if b ~= nil then
enable_logging = b
else
if enable_logging == true then
enable_logging = false
else
enable_logging = true
end
end

if enable_logging then
warn = logfunctions.warn
warning = logfunctions.warn
error = logfunctions.error
info = logfunctions.info
else
warn = function () end
warning = function () end
error = function () end
info = function () end
end
end
toggle (enable_logging)

if flushtonewlog then
os.execute('cmd /c "dir /B /O:D \"'..path..logname..'*\" > \"'..path..'loglist.txt\"')
local f = io.open (path..'loglist.txt','r')
for l in f:lines () do
ins (logs, l)
end
f:close ()
os.remove (path..'loglist.txt')
end

--[[
LSLua Log script 3.0
by cerbie (ernie@doddstech.com)

Primarily made for debugging complicated actions, easily disabled, and
nothing is hidden from anything that wants to look inside. With enough
entries, it automatically flushes to a HTML file. The log appears as a
table, complete with color-codes that are gumdropped in shades.

The main thing that makes this useful is that with all the exec() calls
going on, there are usually tons of good breakpoints in nasty scripts.

Functions to note:
log.warn (source, text): a warning (typically non-fatal problem).
log.error (source, text): a fatal error.
log.info (source, text): something happened.
source and text are both arbitrary strings. The purpose of two
values is purely for easier reading of the table-formatted log.

log.toggle (bool)


log.flush (): writes out to a formatted HTML file named:
$path$logname yyyymmdd hh.mm.ss (millisec).html

If there are more than 'maxlogs', the oldest is removed.

Have fun. Hopefully this will be mildly useful to somebody else! If you
make your own version made from this, just credit me somewhere.
]]

Posted by member 12025 on 2006-12-09 23:18:36 link

Post-posting:

1. It needs to be saved as log.lua under your script module folder.

2. make sure to turn enable_logging to true (3 lines under the module name). It was false when I did the c&p, and I don't feel like feeding the ls.net backslash-eater.

When the wiki is accessible again, I'll put it there with some indenting.

Posted by member 93947 on 2006-12-10 09:07:09 link

uhm, clarify the usage? just require "log" does nothing. Sourround every line with a log.info() or what Oo

Posted by member 12025 on 2006-12-10 17:29:53 link

Oh, OK, require "log" to load it.
log.info (text,text)
log.warn (text,text)
log.warning (text,text)
log.error (text,text)
All add to the current log (for my use, I made them globals).
log.flush () will force it to go out to a file.

Ex:
require "log"
log.info ("modules","loaded xPopup")
log.info ("modules","loaded xTaskbar")
log.info ("modules","loaded ckHotSpots")
log.error ("boxlabels", "this should not be logged. Bad script!")
log.flush ()

Posted by member 93947 on 2006-12-10 18:10:38 link

ooh, i thought it did more^^ well, i use !alert for that^^

Posted by member 12025 on 2006-12-10 20:32:02 link

Yeah, but it locks things and requires user input.