util/logger.lua

changeset 0
73bc20975514
equal deleted inserted replaced
-1:000000000000 0:73bc20975514
1 -- Prosody IM
2 -- Copyright (C) 2008-2010 Matthew Wild
3 -- Copyright (C) 2008-2010 Waqas Hussain
4 --
5 -- This project is MIT/X11 licensed. Please see the
6 -- COPYING file in the source package for more information.
7 --
8
9 local pcall = pcall;
10
11 --local log_sources = config.get("*", "core", "log_sources");
12
13 local find = string.find;
14 local ipairs, pairs, setmetatable = ipairs, pairs, setmetatable;
15
16 module "logger"
17
18 local name_sinks, level_sinks = {}, {};
19 local name_patterns = {};
20
21 -- Weak-keyed so that loggers are collected
22 local modify_hooks = setmetatable({}, { __mode = "k" });
23
24 local make_logger;
25 local outfunction = nil;
26
27 function init(name)
28 if log_sources then
29 local log_this = false;
30 for _, source in ipairs(log_sources) do
31 if find(name, source) then
32 log_this = true;
33 break;
34 end
35 end
36
37 if not log_this then return function () end end
38 end
39
40 local log_debug = make_logger(name, "debug");
41 local log_info = make_logger(name, "info");
42 local log_warn = make_logger(name, "warn");
43 local log_error = make_logger(name, "error");
44
45 --name = nil; -- While this line is not commented, will automatically fill in file/line number info
46 local namelen = #name;
47 return function (level, message, ...)
48 if outfunction then return outfunction(name, level, message, ...); end
49
50 if level == "debug" then
51 return log_debug(message, ...);
52 elseif level == "info" then
53 return log_info(message, ...);
54 elseif level == "warn" then
55 return log_warn(message, ...);
56 elseif level == "error" then
57 return log_error(message, ...);
58 end
59 end
60 end
61
62 function make_logger(source_name, level)
63 local level_handlers = level_sinks[level];
64 if not level_handlers then
65 level_handlers = {};
66 level_sinks[level] = level_handlers;
67 end
68
69 local source_handlers = name_sinks[source_name];
70
71 -- All your premature optimisation is belong to me!
72 local num_level_handlers, num_source_handlers = #level_handlers, source_handlers and #source_handlers;
73
74 local logger = function (message, ...)
75 if source_handlers then
76 for i = 1,num_source_handlers do
77 if source_handlers[i](source_name, level, message, ...) == false then
78 return;
79 end
80 end
81 end
82
83 for i = 1,num_level_handlers do
84 level_handlers[i](source_name, level, message, ...);
85 end
86 end
87
88 -- To make sure our cached lengths stay in sync with reality
89 modify_hooks[logger] = function () num_level_handlers, num_source_handlers = #level_handlers, source_handlers and #source_handlers; end;
90
91 return logger;
92 end
93
94 function setwriter(f)
95 local old_func = outfunction;
96 if not f then outfunction = nil; return true, old_func; end
97 local ok, ret = pcall(f, "logger", "info", "Switched logging output successfully");
98 if ok then
99 outfunction = f;
100 ret = old_func;
101 end
102 return ok, ret;
103 end
104
105 function reset()
106 for k in pairs(name_sinks) do name_sinks[k] = nil; end
107 for level, handler_list in pairs(level_sinks) do
108 -- Clear all handlers for this level
109 for i = 1, #handler_list do
110 handler_list[i] = nil;
111 end
112 end
113 for k in pairs(name_patterns) do name_patterns[k] = nil; end
114
115 for _, modify_hook in pairs(modify_hooks) do
116 modify_hook();
117 end
118 end
119
120 function add_level_sink(level, sink_function)
121 if not level_sinks[level] then
122 level_sinks[level] = { sink_function };
123 else
124 level_sinks[level][#level_sinks[level] + 1 ] = sink_function;
125 end
126
127 for _, modify_hook in pairs(modify_hooks) do
128 modify_hook();
129 end
130 end
131
132 function add_name_sink(name, sink_function, exclusive)
133 if not name_sinks[name] then
134 name_sinks[name] = { sink_function };
135 else
136 name_sinks[name][#name_sinks[name] + 1] = sink_function;
137 end
138
139 for _, modify_hook in pairs(modify_hooks) do
140 modify_hook();
141 end
142 end
143
144 function add_name_pattern_sink(name_pattern, sink_function, exclusive)
145 if not name_patterns[name_pattern] then
146 name_patterns[name_pattern] = { sink_function };
147 else
148 name_patterns[name_pattern][#name_patterns[name_pattern] + 1] = sink_function;
149 end
150 end
151
152 _M.new = make_logger;
153
154 return _M;

mercurial