Comparison

core/loggingmanager.lua @ 7134:b7b6b1d01224

loggingmanager: Refactor the console log sink to re-use the stdout sink which in turn uses the file sink (tailcalls!)
author Kim Alvefur <zash@zash.se>
date Thu, 04 Feb 2016 17:33:16 +0100
parent 7133:ac142f5209d9
child 7135:0b614b7333f1
comparison
equal deleted inserted replaced
7133:ac142f5209d9 7134:b7b6b1d01224
8 8
9 9
10 local format = string.format; 10 local format = string.format;
11 local setmetatable, rawset, pairs, ipairs, type = 11 local setmetatable, rawset, pairs, ipairs, type =
12 setmetatable, rawset, pairs, ipairs, type; 12 setmetatable, rawset, pairs, ipairs, type;
13 local io_open, io_write = io.open, io.write; 13 local stdout = io.stdout;
14 local io_open = io.open;
14 local math_max, rep = math.max, string.rep; 15 local math_max, rep = math.max, string.rep;
15 local os_date = os.date; 16 local os_date = os.date;
16 local getstyle, getstring = require "util.termcolours".getstyle, require "util.termcolours".getstring; 17 local getstyle, getstring = require "util.termcolours".getstyle, require "util.termcolours".getstring;
17 18
18 -- COMPAT: This should no longer be needed since the addition of setvbuf calls 19 -- COMPAT: This should no longer be needed since the addition of setvbuf calls
168 prosody.events.add_handler("config-reloaded", reload_logging); 169 prosody.events.add_handler("config-reloaded", reload_logging);
169 170
170 --- Definition of built-in logging sinks --- 171 --- Definition of built-in logging sinks ---
171 172
172 -- Null sink, must enter log_sink_types *first* 173 -- Null sink, must enter log_sink_types *first*
173 function log_sink_types.nowhere() 174 local function log_to_nowhere()
174 return function () return false; end; 175 return function () return false; end;
175 end 176 end
176 177 log_sink_types.nowhere = log_to_nowhere;
177 -- Column width for "source" (used by stdout and console) 178
178 local sourcewidth = 20; 179 local function log_to_file(sink_config, logfile)
179 180 logfile = logfile or io_open(sink_config.filename, "a+");
180 function log_sink_types.stdout(sink_config) 181 if not logfile then
182 return log_to_nowhere(sink_config);
183 end
184 local write = logfile.write;
185
181 local timestamps = sink_config.timestamps; 186 local timestamps = sink_config.timestamps;
182 187
183 if timestamps == true then 188 if timestamps == true then
184 timestamps = default_timestamp; -- Default format 189 timestamps = default_timestamp; -- Default format
185 end 190 end
186 191
187 if sink_config.buffer_mode ~= false then 192 if sink_config.buffer_mode ~= false then
188 io.stdout:setvbuf(sink_config.buffer_mode or "line");
189 end
190
191 return function (name, level, message, ...)
192 sourcewidth = math_max(#name+2, sourcewidth);
193 local namelen = #name;
194 if timestamps then
195 io_write(os_date(timestamps), " ");
196 end
197 if ... then
198 io_write(name, rep(" ", sourcewidth-namelen), level, "\t", format(message, ...), "\n");
199 else
200 io_write(name, rep(" ", sourcewidth-namelen), level, "\t", message, "\n");
201 end
202 end
203 end
204
205 do
206 local do_pretty_printing = true;
207
208 local logstyles = {};
209 if do_pretty_printing then
210 logstyles["info"] = getstyle("bold");
211 logstyles["warn"] = getstyle("bold", "yellow");
212 logstyles["error"] = getstyle("bold", "red");
213 end
214 function log_sink_types.console(sink_config)
215 -- Really if we don't want pretty colours then just use plain stdout
216 if not do_pretty_printing then
217 return log_sink_types.stdout(sink_config);
218 end
219
220 local timestamps = sink_config.timestamps;
221
222 if timestamps == true then
223 timestamps = default_timestamp; -- Default format
224 end
225
226 if sink_config.buffer_mode ~= false then
227 io.stdout:setvbuf(sink_config.buffer_mode or "line");
228 end
229
230 return function (name, level, message, ...)
231 sourcewidth = math_max(#name+2, sourcewidth);
232 local namelen = #name;
233
234 if timestamps then
235 io_write(os_date(timestamps), " ");
236 end
237 io_write(name, rep(" ", sourcewidth-namelen));
238 io_write(getstring(logstyles[level], level));
239 if ... then
240 io_write("\t", format(message, ...), "\n");
241 else
242 io_write("\t", message, "\n");
243 end
244 end
245 end
246 end
247
248 local empty_function = function () end;
249 function log_sink_types.file(sink_config)
250 local log = sink_config.filename;
251 local logfile = io_open(log, "a+");
252 if not logfile then
253 return empty_function;
254 end
255
256 if sink_config.buffer_mode ~= false then
257 logfile:setvbuf(sink_config.buffer_mode or "line"); 193 logfile:setvbuf(sink_config.buffer_mode or "line");
258 end
259
260 local write = logfile.write;
261
262 local timestamps = sink_config.timestamps;
263
264 if timestamps == nil or timestamps == true then
265 timestamps = default_timestamp; -- Default format
266 end 194 end
267 195
268 return function (name, level, message, ...) 196 return function (name, level, message, ...)
269 if timestamps then 197 if timestamps then
270 write(logfile, os_date(timestamps), " "); 198 write(logfile, os_date(timestamps), " ");
271 end 199 end
272 if ... then 200 if ... then
273 write(logfile, name, "\t", level, "\t", format(message, ...), "\n"); 201 write(logfile, name, level, "\t", format(message, ...), "\n");
274 else 202 else
275 write(logfile, name, "\t" , level, "\t", message, "\n"); 203 write(logfile, name, level, "\t", message, "\n");
276 end 204 end
277 end; 205 end
278 end 206 end
207 log_sink_types.file = log_to_file;
208
209 -- Column width for "source" (used by stdout and console)
210 local sourcewidth = 20;
211
212 local function log_to_stdout(sink_config)
213 if not sink_config.timestamps then
214 sink_config.timestamps = false;
215 end
216 local logtofile = log_to_file(sink_config, stdout);
217 return function (name, level, message, ...)
218 sourcewidth = math_max(#name+2, sourcewidth);
219 name = name .. rep(" ", sourcewidth-#name);
220 return logtofile(name, level, message, ...);
221 end
222 end
223 log_sink_types.stdout = log_to_stdout;
224
225 local do_pretty_printing = true;
226
227 local logstyles;
228 if do_pretty_printing then
229 logstyles = {};
230 logstyles["info"] = getstyle("bold");
231 logstyles["warn"] = getstyle("bold", "yellow");
232 logstyles["error"] = getstyle("bold", "red");
233 end
234
235 local function log_to_console(sink_config)
236 -- Really if we don't want pretty colours then just use plain stdout
237 local logstdout = log_to_stdout(sink_config);
238 if not do_pretty_printing then
239 return logstdout;
240 end
241 return function (name, level, message, ...)
242 local logstyle = logstyles[level];
243 if logstyle then
244 level = getstring(logstyle, level);
245 end
246 return logstdout(name, level, message, ...);
247 end
248 end
249 log_sink_types.console = log_to_console;
279 250
280 local function register_sink_type(name, sink_maker) 251 local function register_sink_type(name, sink_maker)
281 local old_sink_maker = log_sink_types[name]; 252 local old_sink_maker = log_sink_types[name];
282 log_sink_types[name] = sink_maker; 253 log_sink_types[name] = sink_maker;
283 return old_sink_maker; 254 return old_sink_maker;