--- a/mod_http_admin_api/mod_http_admin_api.lua Tue May 25 19:01:54 2021 +0200
+++ b/mod_http_admin_api/mod_http_admin_api.lua Thu May 27 16:18:10 2021 +0200
@@ -3,9 +3,11 @@
local json = require "util.json";
local st = require "util.stanza";
local array = require "util.array";
+local statsmanager = require "core.statsmanager";
module:depends("http");
+local announce = module:depends("announce");
local invites = module:depends("invites");
local tokens = module:depends("tokenauth");
local mod_pep = module:depends("pep");
@@ -578,6 +580,83 @@
});
end
+local function maybe_export_plain_gauge(mf)
+ if mf == nil then
+ return nil
+ end
+ return mf.data.value
+end
+
+local function maybe_export_plain_counter(mf)
+ if mf == nil then
+ return nil
+ end
+ return {
+ since = mf.data._created,
+ value = mf.data.value,
+ }
+end
+
+local function maybe_export_summed_gauge(mf)
+ if mf == nil then
+ return nil
+ end
+ local sum = 0;
+ for _, metric in mf:iter_metrics() do
+ sum = sum + metric.value;
+ end
+ return sum;
+end
+
+local function get_server_metrics(event)
+ event.response.headers["Content-Type"] = json_content_type;
+ local result = {};
+ local families = statsmanager.get_metric_registry():get_metric_families();
+ result.memory = maybe_export_plain_gauge(families.process_resident_memory_bytes);
+ result.cpu = maybe_export_plain_counter(families.process_cpu_seconds);
+ result.c2s = maybe_export_summed_gauge(families["prosody_mod_c2s/connections"])
+ return json.encode(result);
+end
+
+local function post_server_announcement(event)
+ local request = event.request;
+ if request.headers.content_type ~= json_content_type
+ or (not request.body or #request.body == 0) then
+ return 400;
+ end
+ local body = json.decode(event.request.body);
+ if not body then
+ return 400;
+ end
+
+ if type(body.recipients) ~= "table" and body.recipients ~= "online" and body.recipients ~= "all" then
+ return 400;
+ end
+
+ if not body.body or #body.body == 0 then
+ return 400;
+ end
+
+ local message = st.message():tag("body"):text(body.body):up();
+ local host = module.host
+ message.attr.from = host
+ if body.recipients == "online" then
+ announce.send_to_online(message, host);
+ elseif body.recipients == "all" then
+ for username in usermanager.users(host) do
+ message.attr.to = username .. "@" .. host
+ module:send(st.clone(message))
+ end
+ else
+ for _, addr in ipairs(body.recipients) do
+ message.attr.to = addr
+ module:send(message)
+ end
+ end
+
+ return 201;
+end
+
module:provides("http", {
route = check_auth {
["GET /invites"] = list_invites;
@@ -597,5 +676,8 @@
["DELETE /groups/*"] = delete_group;
["GET /server/info"] = get_server_info;
+
+ ["GET /server/metrics"] = get_server_metrics;
+ ["POST /server/announcement"] = post_server_announcement;
};
});
--- a/mod_http_admin_api/openapi.yaml Tue May 25 19:01:54 2021 +0200
+++ b/mod_http_admin_api/openapi.yaml Thu May 27 16:18:10 2021 +0200
@@ -437,6 +437,35 @@
application/json:
schema:
$ref: '#/components/schemas/ServerInfo'
+ /server/metrics:
+ get:
+ tags:
+ - server
+ summary: Get metrics from the running server
+ operationId: getServerMetrics
+ responses:
+ 200:
+ description: successful operation
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServerMetrics'
+ /server/announcement:
+ post:
+ tags:
+ - server
+ summary: Post an announcement to some or all users
+ operationId: postServerAnnouncement
+ requestBody:
+ description: Announcement parameters
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Announcement"
+ responses:
+ 201:
+ description: Announcement has been sent
components:
schemas:
UserList:
@@ -735,4 +764,39 @@
description: A friendly name for the service
version:
type: string
- description: A human-readable version string
\ No newline at end of file
+ description: A human-readable version string
+ ServerMetrics:
+ type: object
+ description: A selection of instantaneous metrics of the prosody server
+ properties:
+ memory:
+ type: integer
+ description: RSS in bytes
+ cpu:
+ type: object
+ description: CPU time counter
+ required:
+ - value
+ - since
+ properties:
+ since:
+ type: float
+ description: The metric epoch as UNIX timestamp
+ value:
+ type: float
+ description: Seconds of CPU time used since the metric epoch
+ c2s:
+ type: integer
+ description: Number of active c2s sessions
+ Announcement:
+ type: object
+ description: An announcemen to post to users on the server
+ required:
+ - body
+ - recipients
+ properties:
+ body:
+ type: string
+ description: The message body to send
+ recipients:
+ description: List of recipients or one of the strings "online" or "all"