+-- Prosody IM
+-- Copyright (C) 2008-2010 Matthew Wild
+-- Copyright (C) 2008-2010 Waqas Hussain
+--
+-- This project is MIT/X11 licensed. Please see the
+-- COPYING file in the source package for more information.
+--
+
local format, rep = string.format, string.rep;
local pcall = pcall;
local debug = debug;
-local tostring, setmetatable, rawset, pairs, ipairs, type =
+local tostring, setmetatable, rawset, pairs, ipairs, type =
tostring, setmetatable, rawset, pairs, ipairs, type;
local io_open, io_write = io.open, io.write;
local math_max, rep = math.max, string.rep;
local os_date, os_getenv = os.date, os.getenv;
-local getstyle, getstring = require "util.termcolours".getstyle, require "util.termcolours".getstring;
+local getstyle, setstyle = require "util.termcolours".getstyle, require "util.termcolours".setstyle;
-local config = require "core.configmanager";
+if os.getenv("__FLUSH_LOG") then
+ local io_flush = io.flush;
+ local _io_write = io_write;
+ io_write = function(...) _io_write(...); io_flush(); end
+end
+local config = require "core.configmanager";
local logger = require "util.logger";
+local prosody = prosody;
+
+local debug_mode = config.get("*", "core", "debug");
_G.log = logger.init("general");
module "loggingmanager"
--- The log config used if none specified in the config file
-local default_logging = { { to = "console" } };
-local default_file_logging = { { to = "file", levels = { min = "info" } } };
-local default_timestamp = "%b %d %T";
+-- The log config used if none specified in the config file (see reload_logging for initialization)
+local default_logging;
+local default_file_logging;
+local default_timestamp = "%b %d %H:%M:%S";
-- The actual config loggingmanager is using
-local logging_config = config.get("*", "core", "log") or default_logging;
+local logging_config;
local apply_sink_rules;
local log_sink_types = setmetatable({}, { __newindex = function (t, k, v) rawset(t, k, v); apply_sink_rules(k); end; });
-- the log_sink_types table.
function apply_sink_rules(sink_type)
if type(logging_config) == "table" then
+
+ if sink_type == "file" then
+ for _, level in ipairs(logging_levels) do
+ if type(logging_config[level]) == "string" then
+ add_rule({
+ to = "file",
+ filename = logging_config[level],
+ timestamps = true,
+ levels = { min = level },
+ });
+ end
+ end
+ end
+
for _, sink_config in pairs(logging_config) do
- if sink_config.to == sink_type then
+ if (type(sink_config) == "table" and sink_config.to == sink_type) then
add_rule(sink_config);
+ elseif (type(sink_config) == "string" and sink_config:match("^%*(.+)") == sink_type) then
+ add_rule({ levels = { min = "debug" }, to = sink_type });
end
end
elseif type(logging_config) == "string" and (not logging_config:match("^%*")) and sink_type == "file" then
- -- User specified simply a filename, and the "file" sink type
+ -- User specified simply a filename, and the "file" sink type
-- was just added
for _, sink_config in pairs(default_file_logging) do
sink_config.filename = logging_config;
add_rule(sink_config);
sink_config.filename = nil;
end
+ elseif type(logging_config) == "string" and logging_config:match("^%*(.+)") == sink_type then
+ -- Log all levels (debug+) to this sink
+ add_rule({ levels = { min = "debug" }, to = sink_type });
end
end
return set;
elseif in_range then
set[level] = true;
- end
+ end
end
end
return set;
end
+-- Initialize config, etc. --
+function reload_logging()
+ local old_sink_types = {};
+
+ for name, sink_maker in pairs(log_sink_types) do
+ old_sink_types[name] = sink_maker;
+ log_sink_types[name] = nil;
+ end
+
+ logger.reset();
+
+ default_logging = { { to = "console" , levels = { min = (debug_mode and "debug") or "info" } } };
+ default_file_logging = {
+ { to = "file", levels = { min = (debug_mode and "debug") or "info" }, timestamps = true }
+ };
+ default_timestamp = "%b %d %H:%M:%S";
+
+ logging_config = config.get("*", "core", "log") or default_logging;
+
+
+ for name, sink_maker in pairs(old_sink_types) do
+ log_sink_types[name] = sink_maker;
+ end
+
+ prosody.events.fire_event("logging-reloaded");
+end
+
+reload_logging();
+prosody.events.add_handler("config-reloaded", reload_logging);
+
--- Definition of built-in logging sinks ---
+-- Null sink, must enter log_sink_types *first*
function log_sink_types.nowhere()
return function () return false; end;
end
if timestamps then
io_write(os_date(timestamps), " ");
end
- if ... then
+ if ... then
io_write(name, rep(" ", sourcewidth-namelen), level, "\t", format(message, ...), "\n");
else
io_write(name, rep(" ", sourcewidth-namelen), level, "\t", message, "\n");
end
- end
+ end
end
do
- local do_pretty_printing = not os_getenv("WINDIR");
+ local do_pretty_printing = true;
local logstyles = {};
if do_pretty_printing then
return function (name, level, message, ...)
sourcewidth = math_max(#name+2, sourcewidth);
local namelen = #name;
+
if timestamps then
io_write(os_date(timestamps), " ");
end
- if ... then
- io_write(name, rep(" ", sourcewidth-namelen), getstring(logstyles[level], level), "\t", format(message, ...), "\n");
+ io_write(name, rep(" ", sourcewidth-namelen));
+ setstyle(logstyles[level]);
+ io_write(level);
+ setstyle();
+ if ... then
+ io_write("\t", format(message, ...), "\n");
else
- io_write(name, rep(" ", sourcewidth-namelen), getstring(logstyles[level], level), "\t", message, "\n");
+ io_write("\t", message, "\n");
end
end
end
end
+local empty_function = function () end;
function log_sink_types.file(config)
local log = config.filename;
local logfile = io_open(log, "a+");
if not logfile then
- return function () end
+ return empty_function;
end
+ local write, flush = logfile.write, logfile.flush;
+
+ prosody.events.add_handler("logging-reloading", function ()
+ if logfile then
+ logfile:close();
+ end
+ end);
local timestamps = config.timestamps;
- if timestamps == true then
+ if timestamps == nil or timestamps == true then
timestamps = default_timestamp; -- Default format
end
- local write, format, flush = logfile.write, format, logfile.flush;
return function (name, level, message, ...)
if timestamps then
write(logfile, os_date(timestamps), " ");
end
- if ... then
+ if ... then
write(logfile, name, "\t", level, "\t", format(message, ...), "\n");
else
write(logfile, name, "\t" , level, "\t", message, "\n");