view mod_log_ringbuffer/mod_log_ringbuffer.lua @ 4210:a0937b5cfdcb

mod_invites_page: Remove preauth URI button This button is incompatible with the majority of XMPP clients around, yet based on feedback from users, many are drawn to click it when they have any XMPP client installed already. In the case where the user already has software installed, we would prefer them to select it from the software list so they can follow the setup process suited to their specific client (we already track which software supports preauth URIs). If their client is not listed, they can still use the manual registration link instead.
author Matthew Wild <mwild1@gmail.com>
date Fri, 16 Oct 2020 11:03:38 +0100
parents 481c4d75e77d
children 86f8ece24029
line wrap: on
line source

module:set_global();

local loggingmanager = require "core.loggingmanager";
local format = require "util.format".format;
local pposix = require "util.pposix";
local rb = require "util.ringbuffer";

local default_timestamp = "%b %d %H:%M:%S ";
local max_chunk_size = module:get_option_number("log_ringbuffer_chunk_size", 16384);

local os_date = os.date;

local default_filename_template = "ringbuffer-logs-{pid}-{count}.log";
local render_filename = require "util.interpolation".new("%b{}", function (s) return s; end, {
	yyyymmdd = function (t)
		return os_date("%Y%m%d", t);
	end;
	hhmmss = function (t)
		return os_date("%H%M%S", t);
	end;
});

local dump_count = 0;

local function dump_buffer(buffer, 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("-- End of dump --\n\n");
	f:close();
end

local function get_filename(filename_template)
	filename_template = filename_template or default_filename_template;
	return render_filename(filename_template, {
		paths = prosody.paths;
		pid = pposix.getpid();
		count = dump_count;
		time = os.time();
	});
end

local function ringbuffer_log_sink_maker(sink_config)
	local buffer = rb.new(sink_config.size or 100*1024);

	local timestamps = sink_config.timestamps;

	if timestamps == true or timestamps == nil then
		timestamps = default_timestamp; -- Default format
	elseif timestamps then
		timestamps = timestamps .. " ";
	end

	local function dump()
		dump_buffer(buffer, get_filename(sink_config.filename));
	end

	if sink_config.signal then
		require "util.signal".signal(sink_config.signal, dump);
	elseif sink_config.event then
		module:hook_global(sink_config.global_event, dump);
	end

	return function (name, level, message, ...)
		buffer:write(format("%s%s\t%s\t%s\n", timestamps and os_date(timestamps) or "", name, level, format(message, ...)));
	end;
end

loggingmanager.register_sink_type("ringbuffer", ringbuffer_log_sink_maker);