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); |
