changeset 4214:5841d54cb6c6

mod_debug_traceback: Descendent of mod_traceback with some additional features
author Matthew Wild <mwild1@gmail.com>
date Fri, 16 Oct 2020 14:23:10 +0100
parents 93a980ac1816
children 86f8ece24029
files mod_debug_traceback/README.markdown mod_debug_traceback/mod_debug_traceback.lua
diffstat 2 files changed, 79 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_debug_traceback/README.markdown	Fri Oct 16 14:23:10 2020 +0100
@@ -0,0 +1,25 @@
+---
+labels:
+- 'Stage-Alpha'
+summary: Generate tracebacks on-demand
+---
+
+# Introduction
+
+This module writes out a traceback to a file when a chosen signal (by default
+`SIGUSR1`) is received. It can be useful to diagnose cases where Prosody is
+unresponsive.
+
+# Configuration
+
+`debug_traceback_filename`
+:   The name of the file to write the traceback to. Some variables
+    are supported, see [mod_log_ringbuffer] docs for more info. Defaults
+    to `{paths.data}/traceback-{pid}-{count}.log`.
+
+`debug_traceback_signal`
+:   The name of the signal to listen for. Defaults to `SIGUSR1`.
+
+# Compatibility
+
+Prosody 0.11 or later.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_debug_traceback/mod_debug_traceback.lua	Fri Oct 16 14:23:10 2020 +0100
@@ -0,0 +1,54 @@
+module:set_global();
+
+local traceback = require "util.debug".traceback;
+local pposix = require "util.pposix";
+local os_date = os.date;
+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 count = 0;
+
+local function get_filename(filename_template)
+	filename_template = filename_template;
+	return render_filename(filename_template, {
+		paths = prosody.paths;
+		pid = pposix.getpid();
+		count = count;
+		time = os.time();
+	});
+end
+
+local default_filename_template = "{paths.data}/traceback-{pid}-{count}.log";
+local filename_template = module:get_option_string("debug_traceback_filename", default_filename_template);
+local signal_name = module:get_option_string("debug_traceback_signal", "SIGUSR1");
+
+function dump_traceback()
+	module:log("info", "Received %s, writing traceback", signal_name);
+
+	local tb = traceback();
+	module:fire_event("debug_traceback/triggered", { traceback = tb });
+
+	local f, err = io.open(get_filename(filename_template), "a+");
+	if not f then
+		module:log("error", "Unable to write traceback: %s", err);
+		return;
+	end
+	f:write("-- Traceback generated at ", os.date("%b %d %H:%M:%S"), " --\n");
+	f:write(traceback(), "\n");
+	f:write("-- End of traceback --\n");
+	f:close();
+	count = count + 1;
+end
+
+local mod_posix = module:depends("posix");
+if mod_posix.features and mod_posix.features.signal_events then
+	module:hook("signal/"..signal_name, dump_traceback);
+else
+	require"util.signal".signal(signal_name, dump_traceback);
+end