--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_audit_status/README.md Fri Apr 07 12:09:21 2023 +0100
@@ -0,0 +1,29 @@
+---
+summary: Log server status changes to audit log
+rockspec: {}
+...
+
+This module records server status (start, stop, crash) to the audit log
+maintained by [mod_audit].
+
+## Configuration
+
+There is a single option, `audit_status_heartbeat_interval` which specifies
+the interval at which the "server is running" heartbeat should be updated (it
+is stored in Prosody's configured storage backend).
+
+To detect crashes, Prosody periodically updates this value at the specified
+interval. A low value will update more frequently, which causes additional I/O
+for Prosody. A high value will give less accurate timestamps for "server
+crashed" events in the audit log.
+
+The default value is 60 (seconds).
+
+```lua
+audit_status_heartbeat_interval = 60
+```
+
+## Compatibility
+
+This module requires Prosody trunk (as of April 2023). It is not compatible
+with 0.12.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_audit_status/mod_audit_status.lua Fri Apr 07 12:09:21 2023 +0100
@@ -0,0 +1,29 @@
+module:depends("audit");
+
+-- Suppress warnings about module:audit()
+-- luacheck: ignore 143/module
+
+local heartbeat_interval = module:get_option_number("audit_status_heartbeat_interval", 60);
+
+local store = module:open_store(nil, "keyval+");
+
+module:hook_global("server-started", function ()
+ local recorded_status = store:get();
+ if recorded_status.status == "started" then
+ module:audit(nil, "server-crashed", { timestamp = recorded_status.heartbeat });
+ end
+ module:audit(nil, "server-started");
+ store:set_key(nil, "status", "started");
+end);
+
+module:hook_global("server-stopped", function ()
+ module:audit(nil, "server-stopped");
+ store:set_key(nil, "status", "stopped");
+end);
+
+if heartbeat_interval then
+ module:add_timer(0, function ()
+ store:set_key(nil, "heartbeat", os.time());
+ return heartbeat_interval;
+ end);
+end