cgi-bin/tek/lib/debug.lua
author Timm S. Mueller <tmueller@neoscientists.org>
Fri, 12 Sep 2008 22:00:42 +0200
changeset 244 3a4291950c9f
parent 226 f16ff668a409
child 247 71a5ca44a68e
permissions -rw-r--r--
luahtml: added UTF-8-to-form encoder written in C; Markup, Debug: minor fixes
and new debugging features merged back in from other projects; FastCGI
launcher: no longer enforces full garbage collection
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@244
    53
_VERSION = "Debug 4.0"
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@244
    65
level = ERROR
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@244
   143
	stderr:write('  tek.lib.debug.dump("app", 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@244
   149
--	dump(name, table): Dump a table
tmueller@244
   150
-------------------------------------------------------------------------------
tmueller@244
   151
tmueller@244
   152
local function basicSerialize(o)
tmueller@244
   153
	if type(o) == "string" then
tmueller@244
   154
		return ("%q"):format(o)
tmueller@244
   155
	elseif type(o) == "userdata" then
tmueller@244
   156
		return "<userdata>"
tmueller@244
   157
	end
tmueller@244
   158
	return tostring(o)
tmueller@244
   159
end
tmueller@244
   160
tmueller@244
   161
function dump(name, value, saved)
tmueller@244
   162
	saved = saved or {}       -- initial value
tmueller@244
   163
	wrout(name, " = ")
tmueller@244
   164
	local t = type(value)
tmueller@244
   165
	if t == "table" then
tmueller@244
   166
		if saved[value] then    -- value already saved?
tmueller@244
   167
			wrout(saved[value], "\n")
tmueller@244
   168
		else
tmueller@244
   169
			saved[value] = name   -- save name for next time
tmueller@244
   170
			wrout("{}\n")
tmueller@244
   171
			for k,v in pairs(value) do      -- save its fields
tmueller@244
   172
				local fieldname = ("%s[%s]"):format(name, basicSerialize(k))
tmueller@244
   173
				dump(fieldname, v, saved)
tmueller@244
   174
			end
tmueller@244
   175
		end
tmueller@244
   176
	else
tmueller@244
   177
		wrout(basicSerialize(value), "\n")
tmueller@244
   178
	end
tmueller@244
   179
end