Mercurial > prosody-modules
comparison mod_log_ringbuffer/mod_log_ringbuffer.lua @ 4226:df2ccb42a241
mod_log_ringbuffer: Add 'lines' option (actually an alternative ringbuffer implementation)
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Tue, 20 Oct 2020 15:54:07 +0100 |
parents | d6fb9f7afaa5 |
children | 133b23758cf6 |
comparison
equal
deleted
inserted
replaced
4225:d6fb9f7afaa5 | 4226:df2ccb42a241 |
---|---|
2 | 2 |
3 local loggingmanager = require "core.loggingmanager"; | 3 local loggingmanager = require "core.loggingmanager"; |
4 local format = require "util.format".format; | 4 local format = require "util.format".format; |
5 local pposix = require "util.pposix"; | 5 local pposix = require "util.pposix"; |
6 local rb = require "util.ringbuffer"; | 6 local rb = require "util.ringbuffer"; |
7 local queue = require "util.queue"; | |
7 | 8 |
8 local default_timestamp = "%b %d %H:%M:%S "; | 9 local default_timestamp = "%b %d %H:%M:%S "; |
9 local max_chunk_size = module:get_option_number("log_ringbuffer_chunk_size", 16384); | 10 local max_chunk_size = module:get_option_number("log_ringbuffer_chunk_size", 16384); |
10 | 11 |
11 local os_date = os.date; | 12 local os_date = os.date; |
20 end; | 21 end; |
21 }); | 22 }); |
22 | 23 |
23 local dump_count = 0; | 24 local dump_count = 0; |
24 | 25 |
25 local function dump_buffer(buffer, filename) | 26 local function dump_buffer(dump, filename) |
26 dump_count = dump_count + 1; | 27 dump_count = dump_count + 1; |
27 local f, err = io.open(filename, "a+"); | 28 local f, err = io.open(filename, "a+"); |
28 if not f then | 29 if not f then |
29 module:log("error", "Unable to open output file: %s", err); | 30 module:log("error", "Unable to open output file: %s", err); |
30 return; | 31 return; |
31 end | 32 end |
32 local bytes_remaining = buffer:length(); | 33 f:write(("-- Dumping log buffer at %s --\n"):format(os_date(default_timestamp))); |
33 f:write(("-- Dumping %d bytes at %s --\n"):format(bytes_remaining, os_date(default_timestamp))); | 34 dump(f); |
34 while bytes_remaining > 0 do | |
35 local chunk_size = math.min(bytes_remaining, max_chunk_size); | |
36 local chunk = buffer:read(chunk_size); | |
37 if not chunk then | |
38 f:write("-- Dump aborted due to error --\n\n"); | |
39 f:close(); | |
40 return; | |
41 end | |
42 f:write(chunk); | |
43 bytes_remaining = bytes_remaining - chunk_size; | |
44 end | |
45 f:write("-- End of dump --\n\n"); | 35 f:write("-- End of dump --\n\n"); |
46 f:close(); | 36 f:close(); |
47 end | 37 end |
48 | 38 |
49 local function get_filename(filename_template) | 39 local function get_filename(filename_template) |
54 count = dump_count; | 44 count = dump_count; |
55 time = os.time(); | 45 time = os.time(); |
56 }); | 46 }); |
57 end | 47 end |
58 | 48 |
49 local function new_buffer(config) | |
50 local write, dump; | |
51 | |
52 if config.lines then | |
53 local buffer = queue.new(config.lines, true); | |
54 function write(line) | |
55 buffer:push(line); | |
56 end | |
57 function dump(f) | |
58 -- COMPAT w/0.11 - update to use :consume() | |
59 for line in buffer.pop, buffer do | |
60 f:write(line); | |
61 end | |
62 end | |
63 else | |
64 local buffer_size = config.size or 100*1024; | |
65 local buffer = rb.new(buffer_size); | |
66 function write(line) | |
67 if not buffer:write(line) then | |
68 if #line > buffer_size then | |
69 buffer:discard(buffer_size); | |
70 buffer:write(line:sub(-buffer_size)); | |
71 else | |
72 buffer:discard(#line); | |
73 buffer:write(line); | |
74 end | |
75 end | |
76 end | |
77 function dump(f) | |
78 local bytes_remaining = buffer:length(); | |
79 while bytes_remaining > 0 do | |
80 local chunk_size = math.min(bytes_remaining, max_chunk_size); | |
81 local chunk = buffer:read(chunk_size); | |
82 if not chunk then | |
83 return; | |
84 end | |
85 f:write(chunk); | |
86 bytes_remaining = bytes_remaining - chunk_size; | |
87 end | |
88 end | |
89 end | |
90 return write, dump; | |
91 end | |
92 | |
59 local function ringbuffer_log_sink_maker(sink_config) | 93 local function ringbuffer_log_sink_maker(sink_config) |
60 local buffer_size = sink_config.size or 100*1024; | 94 local write, dump = new_buffer(sink_config); |
61 local buffer = rb.new(buffer_size); | |
62 | 95 |
63 local timestamps = sink_config.timestamps; | 96 local timestamps = sink_config.timestamps; |
64 | 97 |
65 if timestamps == true or timestamps == nil then | 98 if timestamps == true or timestamps == nil then |
66 timestamps = default_timestamp; -- Default format | 99 timestamps = default_timestamp; -- Default format |
67 elseif timestamps then | 100 elseif timestamps then |
68 timestamps = timestamps .. " "; | 101 timestamps = timestamps .. " "; |
69 end | 102 end |
70 | 103 |
71 local function dump() | 104 local function handler() |
72 dump_buffer(buffer, sink_config.filename or get_filename(sink_config.filename_template)); | 105 dump_buffer(dump, sink_config.filename or get_filename(sink_config.filename_template)); |
73 end | 106 end |
74 | 107 |
75 if sink_config.signal then | 108 if sink_config.signal then |
76 require "util.signal".signal(sink_config.signal, dump); | 109 require "util.signal".signal(sink_config.signal, handler); |
77 elseif sink_config.event then | 110 elseif sink_config.event then |
78 module:hook_global(sink_config.event, dump); | 111 module:hook_global(sink_config.event, handler); |
79 end | 112 end |
80 | 113 |
81 return function (name, level, message, ...) | 114 return function (name, level, message, ...) |
82 local line = format("%s%s\t%s\t%s\n", timestamps and os_date(timestamps) or "", name, level, format(message, ...)); | 115 local line = format("%s%s\t%s\t%s\n", timestamps and os_date(timestamps) or "", name, level, format(message, ...)); |
83 if not buffer:write(line) then | 116 write(line); |
84 if #line > buffer_size then | |
85 buffer:discard(buffer_size); | |
86 buffer:write(line:sub(-buffer_size)); | |
87 else | |
88 buffer:discard(#line); | |
89 buffer:write(line); | |
90 end | |
91 end | |
92 end; | 117 end; |
93 end | 118 end |
94 | 119 |
95 loggingmanager.register_sink_type("ringbuffer", ringbuffer_log_sink_maker); | 120 loggingmanager.register_sink_type("ringbuffer", ringbuffer_log_sink_maker); |