mod_log_ringbuffer: Add 'lines' option (actually an alternative ringbuffer implementation)
--- a/mod_log_ringbuffer/README.markdown Tue Oct 20 15:34:29 2020 +0100
+++ b/mod_log_ringbuffer/README.markdown Tue Oct 20 15:54:07 2020 +0100
@@ -50,6 +50,10 @@
: The size, in bytes, of the buffer. When the buffer fills,
old data will be overwritten by new data.
+`lines`
+: If specified, preserves the latest N complete lines in the
+ buffer. The `size` option is ignored when this option is set.
+
`filename`
: The name of the file to dump logs to when triggered.
--- a/mod_log_ringbuffer/mod_log_ringbuffer.lua Tue Oct 20 15:34:29 2020 +0100
+++ b/mod_log_ringbuffer/mod_log_ringbuffer.lua Tue Oct 20 15:54:07 2020 +0100
@@ -4,6 +4,7 @@
local format = require "util.format".format;
local pposix = require "util.pposix";
local rb = require "util.ringbuffer";
+local queue = require "util.queue";
local default_timestamp = "%b %d %H:%M:%S ";
local max_chunk_size = module:get_option_number("log_ringbuffer_chunk_size", 16384);
@@ -22,26 +23,15 @@
local dump_count = 0;
-local function dump_buffer(buffer, filename)
+local function dump_buffer(dump, filename)
dump_count = dump_count + 1;
local f, err = io.open(filename, "a+");
if not f then
module:log("error", "Unable to open output file: %s", err);
return;
end
- local bytes_remaining = buffer:length();
- f:write(("-- Dumping %d bytes at %s --\n"):format(bytes_remaining, os_date(default_timestamp)));
- while bytes_remaining > 0 do
- local chunk_size = math.min(bytes_remaining, max_chunk_size);
- local chunk = buffer:read(chunk_size);
- if not chunk then
- f:write("-- Dump aborted due to error --\n\n");
- f:close();
- return;
- end
- f:write(chunk);
- bytes_remaining = bytes_remaining - chunk_size;
- end
+ f:write(("-- Dumping log buffer at %s --\n"):format(os_date(default_timestamp)));
+ dump(f);
f:write("-- End of dump --\n\n");
f:close();
end
@@ -56,9 +46,52 @@
});
end
+local function new_buffer(config)
+ local write, dump;
+
+ if config.lines then
+ local buffer = queue.new(config.lines, true);
+ function write(line)
+ buffer:push(line);
+ end
+ function dump(f)
+ -- COMPAT w/0.11 - update to use :consume()
+ for line in buffer.pop, buffer do
+ f:write(line);
+ end
+ end
+ else
+ local buffer_size = config.size or 100*1024;
+ local buffer = rb.new(buffer_size);
+ function write(line)
+ if not buffer:write(line) then
+ if #line > buffer_size then
+ buffer:discard(buffer_size);
+ buffer:write(line:sub(-buffer_size));
+ else
+ buffer:discard(#line);
+ buffer:write(line);
+ end
+ end
+ end
+ function dump(f)
+ local bytes_remaining = buffer:length();
+ while bytes_remaining > 0 do
+ local chunk_size = math.min(bytes_remaining, max_chunk_size);
+ local chunk = buffer:read(chunk_size);
+ if not chunk then
+ return;
+ end
+ f:write(chunk);
+ bytes_remaining = bytes_remaining - chunk_size;
+ end
+ end
+ end
+ return write, dump;
+end
+
local function ringbuffer_log_sink_maker(sink_config)
- local buffer_size = sink_config.size or 100*1024;
- local buffer = rb.new(buffer_size);
+ local write, dump = new_buffer(sink_config);
local timestamps = sink_config.timestamps;
@@ -68,27 +101,19 @@
timestamps = timestamps .. " ";
end
- local function dump()
- dump_buffer(buffer, sink_config.filename or get_filename(sink_config.filename_template));
+ local function handler()
+ dump_buffer(dump, sink_config.filename or get_filename(sink_config.filename_template));
end
if sink_config.signal then
- require "util.signal".signal(sink_config.signal, dump);
+ require "util.signal".signal(sink_config.signal, handler);
elseif sink_config.event then
- module:hook_global(sink_config.event, dump);
+ module:hook_global(sink_config.event, handler);
end
return function (name, level, message, ...)
local line = format("%s%s\t%s\t%s\n", timestamps and os_date(timestamps) or "", name, level, format(message, ...));
- if not buffer:write(line) then
- if #line > buffer_size then
- buffer:discard(buffer_size);
- buffer:write(line:sub(-buffer_size));
- else
- buffer:discard(#line);
- buffer:write(line);
- end
- end
+ write(line);
end;
end