+-- Prosody IM
+-- Copyright (C) 2008-2009 Matthew Wild
+-- Copyright (C) 2008-2009 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;
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_getenv = os.getenv;
+local os_date, os_getenv = os.date, os.getenv;
local getstyle, getstring = require "util.termcolours".getstyle, require "util.termcolours".getstring;
local config = require "core.configmanager";
-
+local eventmanager = require "core.eventmanager";
local logger = require "util.logger";
+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 = (debug_mode and "debug") or "info" }, timestamps = true } };
+local default_timestamp = "%b %d %T";
-- The actual config loggingmanager is using
local logging_config = config.get("*", "core", "log") or default_logging;
local get_levels;
local logging_levels = { "debug", "info", "warn", "error", "critical" }
+-- Put a rule into action. Requires that the sink type has already been registered.
+-- This function is called automatically when a new sink type is added [see apply_sink_rules()]
local function add_rule(sink_config)
local sink_maker = log_sink_types[sink_config.to];
if sink_maker then
end
end
--- Search for all rules using a particular sink type,
--- and apply them
+-- Search for all rules using a particular sink type, and apply
+-- them. Called automatically when a new sink type is added to
+-- the log_sink_types table.
function apply_sink_rules(sink_type)
if type(logging_config) == "table" then
for _, sink_config in pairs(logging_config) do
add_rule(sink_config);
end
end
- elseif type(logging_config) == "string" and sink_type == "file" then
+ 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
-- 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
--- 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
local sourcewidth = 20;
function log_sink_types.stdout()
+ local timestamps = config.timestamps;
+
+ if timestamps == true then
+ timestamps = default_timestamp; -- Default format
+ end
+
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), level, "\t", format(message, ...), "\n");
else
return log_sink_types.stdout(config);
end
+ local timestamps = config.timestamps;
+
+ if timestamps == true then
+ timestamps = default_timestamp; -- Default format
+ end
+
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");
else
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;
+
+ eventmanager.add_event_hook("reopen-log-files", function ()
+ if logfile then
+ logfile:close();
+ end
+ logfile = io_open(log, "a+");
+ if not logfile then
+ write, flush = empty_function, empty_function;
+ else
+ write, flush = logfile.write, logfile.flush;
+ end
+ end);
+
+ local timestamps = config.timestamps;
+
+ 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
write(logfile, name, "\t", level, "\t", format(message, ...), "\n");
else