Changeset

1018:686fbeb411e3

Merge with 0.4.1
author Matthew Wild <mwild1@gmail.com>
date Tue, 21 Apr 2009 03:39:32 +0100
parents 1014:a72e285f7510 (current diff) 1017:6556a9db3822 (diff)
children 1019:8d750336e517
files
diffstat 3 files changed, 143 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/loggingmanager.lua	Tue Apr 21 03:39:32 2009 +0100
@@ -0,0 +1,49 @@
+
+local format, rep = string.format, string.rep;
+local io_write = io.write;
+local pcall = pcall;
+local debug = debug;
+local tostring = tostring;
+local math_max = math.max;
+
+local logger = require "util.logger";
+
+-- Global log function, because some people are too 
+-- lazy to get their own
+_G.log = logger.init("general");
+
+-- Disable log output, needs to read from config
+-- logger.setwriter(function () end);
+
+local getstyle, getstring = require "util.termcolours".getstyle, require "util.termcolours".getstring;
+local do_pretty_printing = not os.getenv("WINDIR");
+
+local logstyles = {};
+
+--TODO: This should be done in config, but we don't have proper config yet
+if do_pretty_printing then
+	logstyles["info"] = getstyle("bold");
+	logstyles["warn"] = getstyle("bold", "yellow");
+	logstyles["error"] = getstyle("bold", "red");
+end
+
+local sourcewidth = 20;
+local math_max, rep = math.max, string.rep;
+local function make_default_log_sink(level)
+	return function (name, _level, message, ...)
+		sourcewidth = math_max(#name+2, sourcewidth);
+		local namelen = #name;
+		if ... then 
+			io_write(name, rep(" ", sourcewidth-namelen), getstring(logstyles[level], level), "\t", format(message, ...), "\n");
+		else
+			io_write(name, rep(" ", sourcewidth-namelen), getstring(logstyles[level], level), "\t", message, "\n");
+		end
+	end
+end
+
+-- Set default sinks
+logger.add_level_sink("debug", make_default_log_sink("debug"));
+logger.add_level_sink("info", make_default_log_sink("info"));
+logger.add_level_sink("warn", make_default_log_sink("warn"));
+logger.add_level_sink("error", make_default_log_sink("error"));
+
--- a/prosody	Mon Apr 20 22:25:49 2009 +0100
+++ b/prosody	Tue Apr 21 03:39:32 2009 +0100
@@ -59,22 +59,22 @@
 	end
 end
 
-log = require "util.logger".init("general");
+--- Initialize logging
+require "core.loggingmanager"
 
--- Disable log output, needs to read from config
--- require "util.logger".setwriter(function () end);
-
+--- Check runtime dependencies
 require "util.dependencies"
 
+--- Load socket framework
 local server = require "net.server"
 
 
+
 -- Maps connections to sessions --
 sessions = {};
 hosts = {};
 
--- Load and initialise core modules --
-
+--- Load and initialise core modules
 require "util.import"
 require "core.xmlhandlers"
 require "core.rostermanager"
--- a/util/logger.lua	Mon Apr 20 22:25:49 2009 +0100
+++ b/util/logger.lua	Tue Apr 21 03:39:32 2009 +0100
@@ -6,34 +6,23 @@
 -- COPYING file in the source package for more information.
 --
 
-local format, rep = string.format, string.rep;
-local io_write = io.write;
 local pcall = pcall;
-local debug = debug;
-local tostring = tostring;
-local math_max = math.max;
 
 local config = require "core.configmanager";
 local log_sources = config.get("*", "core", "log_sources");
 
-local getstyle, getstring = require "util.termcolours".getstyle, require "util.termcolours".getstring;
-local do_pretty_printing = not os.getenv("WINDIR");
 local find = string.find;
-local ipairs = ipairs;
+local ipairs, pairs, setmetatable = ipairs, pairs, setmetatable;
 
 module "logger"
 
-local logstyles = {};
+local name_sinks, level_sinks = {}, {};
+local name_patterns = {};
 
---TODO: This should be done in config, but we don't have proper config yet
-if do_pretty_printing then
-	logstyles["info"] = getstyle("bold");
-	logstyles["warn"] = getstyle("bold", "yellow");
-	logstyles["error"] = getstyle("bold", "red");
-end
+-- Weak-keyed so that loggers are collected
+local modify_hooks = setmetatable({}, { __mode = "k" });
 
-local sourcewidth = 20;
-
+local make_logger;
 local outfunction = nil;
 
 function init(name)
@@ -49,18 +38,58 @@
 		if not log_this then return function () end end
 	end
 	
+	local log_debug = make_logger(name, "debug");
+	local log_info = make_logger(name, "info");
+	local log_warn = make_logger(name, "warn");
+	local log_error = make_logger(name, "error");
+
 	--name = nil; -- While this line is not commented, will automatically fill in file/line number info
 	local namelen = #name;
-	return 	function (level, message, ...)
-				if outfunction then return outfunction(name, level, message, ...); end
-				
-				sourcewidth = math_max(#name+2, sourcewidth);
-				if ... then 
-					io_write(name, rep(" ", sourcewidth-namelen), getstring(logstyles[level], level), "\t", format(message, ...), "\n");
-				else
-					io_write(name, rep(" ", sourcewidth-namelen), getstring(logstyles[level], level), "\t", message, "\n");
+	return function (level, message, ...)
+			if outfunction then return outfunction(name, level, message, ...); end
+			
+			if level == "debug" then
+				return log_debug(message, ...);
+			elseif level == "info" then
+				return log_info(message, ...);
+			elseif level == "warn" then
+				return log_warn(message, ...);
+			elseif level == "error" then
+				return log_error(message, ...);
+			end
+		end
+end
+
+function make_logger(source_name, level)
+	local level_handlers = level_sinks[level];
+	if not level_handlers then
+		level_handlers = {};
+		level_sinks[level] = level_handlers;
+	end
+
+	local source_handlers = name_sinks[source_name];
+	
+	-- All your premature optimisation is belong to me!
+	local num_level_handlers, num_source_handlers = #level_handlers, source_handlers and #source_handlers;
+	
+	local logger = function (message, ...)
+		if source_handlers then
+			for i = 1,num_source_handlers do
+				if source_handlers(source_name, level, message, ...) == false then
+					return;
 				end
 			end
+		end
+		
+		for i = 1,num_level_handlers do
+			level_handlers[i](source_name, level, message, ...);
+		end
+	end
+
+	-- To make sure our cached lengths stay in sync with reality
+	modify_hooks[logger] = function () num_level_handlers, num_source_handlers = #level_handlers, source_handlers and #source_handlers; end; 
+	
+	return logger;
 end
 
 function setwriter(f)
@@ -74,4 +103,38 @@
 	return ok, ret;
 end
 
+function add_level_sink(level, sink_function)
+	if not level_sinks[level] then
+		level_sinks[level] = { sink_function };
+	else
+		level_sinks[level][#level_sinks[level] + 1 ] = sink_function;
+	end
+	
+	for _, modify_hook in pairs(modify_hooks) do
+		modify_hook();
+	end
+end
+
+function add_name_sink(name, sink_function, exclusive)
+	if not name_sinks[name] then
+		name_sinks[name] = { sink_function };
+	else
+		name_sinks[name][#name_sinks[name] + 1] = sink_function;
+	end
+	
+	for _, modify_hook in pairs(modify_hooks) do
+		modify_hook();
+	end
+end
+
+function add_name_pattern_sink(name_pattern, sink_function, exclusive)
+	if not name_patterns[name_pattern] then
+		name_patterns[name_pattern] = { sink_function };
+	else
+		name_patterns[name_pattern][#name_patterns[name_pattern] + 1] = sink_function;
+	end
+end
+
+_M.new = make_logger;
+
 return _M;