cgi-bin/tek/lib/debug.lua
author Timm S. Mueller <tmueller@neoscientists.org>
Fri, 24 Oct 2008 01:35:27 +0200
changeset 251 2de5931b723d
parent 244 3a4291950c9f
child 255 63e76b4e3956
permissions -rw-r--r--
tek.os.posix has been moved to tek.lib.posix, module initialization procedure
simplified, added statvfs() under Linux
tmueller@226
     1
-------------------------------------------------------------------------------
tmueller@201
     2
--
tmueller@201
     3
--	tek.lib.debug
tmueller@244
     4
--	Written by Timm S. Mueller <tmueller at schulze-mueller.de>
tmueller@201
     5
--	See copyright notice in COPYRIGHT
tmueller@201
     6
--
tmueller@226
     7
--	OVERVIEW::
tmueller@226
     8
--	Debug library - implements debug output and debug levels:
tmueller@226
     9
--
tmueller@244
    10
--	2  || TRACE || used for tracking bugs
tmueller@244
    11
--	4  || INFO  || informational messages
tmueller@244
    12
--	5  || WARN  || something unexpected happened
tmueller@244
    13
--	10 || ERROR || something went wrong, e.g. resource unavailable
tmueller@244
    14
--	20 || FAIL  || something went wrong that can't be coped with
tmueller@226
    15
--
tmueller@244
    16
--	The default debug level is 10 {{ERROR}}. To set the debug level
tmueller@226
    17
--	globally, e.g.:
tmueller@226
    18
--			db = require "tek.lib.debug"
tmueller@244
    19
--			db.level = db.INFO
tmueller@226
    20
--
tmueller@226
    21
--	The default debug output stream is {{stderr}}.
tmueller@226
    22
--	To override it globally, e.g.:
tmueller@226
    23
--			db = require "tek.lib.debug"
tmueller@244
    24
--			db.out = io.open("logfile", "w")
tmueller@244
    25
--
tmueller@244
    26
--	FUNCTIONS::
tmueller@244
    27
--		- debug.console() - Enter debug console
tmueller@244
    28
--		- debug.dump() - Dump a table recursively
tmueller@244
    29
--		- debug.error() - Print a text in the {{ERROR}} debug level
tmueller@244
    30
--		- debug.execute() - Execute a function in the specified debug level
tmueller@244
    31
--		- debug.fail() - Print a text in the {{FAIL}} debug level
tmueller@244
    32
--		- debug.info() - Print a text in the {{INFO}} debug level
tmueller@244
    33
--		- debug.print() - Print a text in the specified debug level
tmueller@244
    34
--		- debug.stacktrace() - Print a stacktrace in the specified debug level
tmueller@244
    35
--		- debug.trace() - Print a text in the {{TRACE}} debug level
tmueller@244
    36
--		- debug.warn() - Print a text in the {{WARN}} debug level
tmueller@226
    37
--
tmueller@226
    38
-------------------------------------------------------------------------------
tmueller@201
    39
tmueller@244
    40
local debug = require "debug"
tmueller@244
    41
local getinfo = debug.getinfo
tmueller@244
    42
local stderr = io.stderr
tmueller@244
    43
local pairs = pairs
tmueller@244
    44
local select = select
tmueller@244
    45
local time = os.time
tmueller@244
    46
local tonumber = tonumber
tmueller@201
    47
local tostring = tostring
tmueller@244
    48
local traceback = debug.traceback
tmueller@201
    49
local type = type
tmueller@201
    50
local unpack = unpack
tmueller@201
    51
tmueller@201
    52
module "tek.lib.debug"
tmueller@247
    53
_VERSION = "Debug 4.1"
tmueller@244
    54
tmueller@244
    55
-- symbolic:
tmueller@244
    56
tmueller@244
    57
TRACE = 2
tmueller@244
    58
INFO = 4
tmueller@244
    59
WARN = 5
tmueller@244
    60
ERROR = 10
tmueller@244
    61
FAIL = 20
tmueller@201
    62
tmueller@226
    63
-- global defaults:
tmueller@244
    64
tmueller@247
    65
level = INFO
tmueller@244
    66
out = stderr
tmueller@244
    67
wrout = function(...) out:write(...) end
tmueller@226
    68
tmueller@226
    69
-------------------------------------------------------------------------------
tmueller@244
    70
--	print(lvl, msg, ...): Prints formatted text if the global debug level
tmueller@226
    71
--	is less or equal the specified level.
tmueller@226
    72
-------------------------------------------------------------------------------
tmueller@201
    73
tmueller@201
    74
function print(lvl, msg, ...)
tmueller@201
    75
	if level and lvl >= level then
tmueller@201
    76
		local t = getinfo(3, "lS")
tmueller@201
    77
		local arg = { }
tmueller@205
    78
		for i = 1, select('#', ...) do
tmueller@205
    79
			local v = select(i, ...)
tmueller@226
    80
			arg[i] = v and type(v) ~= "number" and tostring(v) or v or 0
tmueller@201
    81
		end
tmueller@244
    82
		wrout(("(%02d %d %s:%d) " .. msg):format(lvl,
tmueller@226
    83
			time(), t.short_src, t.currentline, unpack(arg)) .. "\n")
tmueller@201
    84
	end
tmueller@201
    85
end
tmueller@201
    86
tmueller@226
    87
-------------------------------------------------------------------------------
tmueller@244
    88
--	execute(lvl, func, ...): Executes the specified function if the global
tmueller@226
    89
--	debug library is less or equal the specified level.
tmueller@226
    90
-------------------------------------------------------------------------------
tmueller@226
    91
tmueller@205
    92
function execute(lvl, func, ...)
tmueller@205
    93
	if level and lvl >= level then
tmueller@226
    94
		return func(...)
tmueller@205
    95
	end
tmueller@201
    96
end
tmueller@201
    97
tmueller@226
    98
-------------------------------------------------------------------------------
tmueller@244
    99
--	trace(msg, ...): Prints formatted debug info with {{TRACE}} level
tmueller@226
   100
-------------------------------------------------------------------------------
tmueller@205
   101
function trace(msg, ...) print(2, msg, ...) end
tmueller@226
   102
tmueller@226
   103
-------------------------------------------------------------------------------
tmueller@244
   104
--	info(msg, ...): Prints formatted debug info with {{INFO}} level
tmueller@226
   105
-------------------------------------------------------------------------------
tmueller@205
   106
function info(msg, ...) print(4, msg, ...) end
tmueller@226
   107
tmueller@226
   108
-------------------------------------------------------------------------------
tmueller@244
   109
--	warn(msg, ...): Prints formatted debug info with {{WARN}} level
tmueller@226
   110
-------------------------------------------------------------------------------
tmueller@205
   111
function warn(msg, ...) print(5, msg, ...) end
tmueller@226
   112
tmueller@226
   113
-------------------------------------------------------------------------------
tmueller@244
   114
--	error(msg, ...): Prints formatted debug info with {{ERROR}} level
tmueller@226
   115
-------------------------------------------------------------------------------
tmueller@205
   116
function error(msg, ...) print(10, msg, ...) end
tmueller@226
   117
tmueller@226
   118
-------------------------------------------------------------------------------
tmueller@244
   119
--	fail(msg, ...): Prints formatted debug info with {{FAIL}} level
tmueller@226
   120
-------------------------------------------------------------------------------
tmueller@205
   121
function fail(msg, ...) print(20, msg, ...) end
tmueller@201
   122
tmueller@244
   123
-------------------------------------------------------------------------------
tmueller@244
   124
--	stacktrace(debuglevel, stacklevel): Prints a stacktrace starting at
tmueller@244
   125
--	the function of the given {{level}} on the stack (excluding the
tmueller@244
   126
--	{{stracktrace}} function itself) if the global debug level is less
tmueller@244
   127
--	or equal the specified {{debuglevel}}.
tmueller@244
   128
-------------------------------------------------------------------------------
tmueller@244
   129
tmueller@244
   130
function stacktrace(lvl, level)
tmueller@244
   131
	print(lvl, traceback("", level or 1 + 1))
tmueller@244
   132
end
tmueller@244
   133
tmueller@244
   134
-------------------------------------------------------------------------------
tmueller@244
   135
--	console(): Enter the debug console.
tmueller@244
   136
-------------------------------------------------------------------------------
tmueller@244
   137
tmueller@244
   138
function console()
tmueller@244
   139
	stderr:write('Entering the debug console.\n')
tmueller@244
   140
	stderr:write('To redirect the output, e.g.:\n')
tmueller@244
   141
	stderr:write('  tek.lib.debug.out = io.open("logfile", "w")\n')
tmueller@244
   142
	stderr:write('To dump a table, e.g.:\n')
tmueller@247
   143
	stderr:write('  tek.lib.debug.dump(app)\n')
tmueller@244
   144
	stderr:write('Use "cont" to continue.\n')
tmueller@244
   145
	debug.debug()
tmueller@244
   146
end
tmueller@244
   147
tmueller@244
   148
-------------------------------------------------------------------------------
tmueller@247
   149
--	dump(table): Dump a table as Lua source using {{out}} as the output
tmueller@247
   150
--	stream. Cyclic references are silently dropped.
tmueller@244
   151
-------------------------------------------------------------------------------
tmueller@244
   152
tmueller@247
   153
local function encodenonascii(c)
tmueller@247
   154
	return ("\\%03d"):format(c:byte())
tmueller@244
   155
end
tmueller@244
   156
tmueller@247
   157
local function encode(s)
tmueller@247
   158
	return s:gsub('([%z\001-\031\092"])', encodenonascii)
tmueller@247
   159
end
tmueller@247
   160
tmueller@247
   161
local function dumpr(tab, indent, outfunc, saved)
tmueller@247
   162
	saved[tab] = tab
tmueller@247
   163
	local is = ("\t"):rep(indent)
tmueller@247
   164
	for key, val in pairs(tab) do
tmueller@247
   165
		if not saved[val] then
tmueller@247
   166
			outfunc(is)
tmueller@247
   167
			local t = type(key)
tmueller@247
   168
			if t == "number" or t == "boolean" then
tmueller@247
   169
				outfunc('[' .. tostring(key) .. '] = ')
tmueller@247
   170
			elseif t == "string" then
tmueller@247
   171
				if key:match("[^%a_]") then
tmueller@247
   172
					outfunc('["' .. encode(key) .. '"] = ')
tmueller@247
   173
				else
tmueller@247
   174
					outfunc(key .. ' = ')
tmueller@247
   175
				end
tmueller@247
   176
			else
tmueller@247
   177
				outfunc('["' .. tostring(key) .. '"] = ')
tmueller@247
   178
			end
tmueller@247
   179
			t = type(val)
tmueller@247
   180
			if t == "table" then
tmueller@247
   181
				outfunc('{\n')
tmueller@247
   182
				dumpr(val, indent + 1, outfunc, saved)
tmueller@247
   183
				outfunc(is .. '},\n')
tmueller@247
   184
			elseif t == "string" then
tmueller@247
   185
				outfunc('"' .. encode(val) .. '",\n')
tmueller@247
   186
			elseif t == "number" or t == "boolean" then
tmueller@247
   187
				outfunc(tostring(val) .. ',\n')
tmueller@247
   188
			else
tmueller@247
   189
				outfunc('"' .. tostring(val) .. '",\n')
tmueller@244
   190
			end
tmueller@244
   191
		end
tmueller@244
   192
	end
tmueller@244
   193
end
tmueller@247
   194
tmueller@247
   195
function dump(tab, outf)
tmueller@247
   196
	dumpr(tab, 0, outf or wrout, { })
tmueller@247
   197
end