mod_prometheus/mod_prometheus.lua
author Matthew Wild <mwild1@gmail.com>
Tue, 18 Jan 2022 17:01:18 +0000
changeset 4880 0f5f2d4475b9
parent 4600 c406e4bf7ee5
permissions -rw-r--r--
mod_http_xep227: Add support for import via APIs rather than direct store manipulation In particular this transitions PEP nodes and data to be imported via mod_pep's APIs, fixing issues with importing at runtime while PEP data may already be live in RAM. Next obvious candidate for this approach is rosters, so clients get immediate roster pushes and other special handling (such as emitting subscribes to reach the desired subscription state).
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
3136
4ef28b6b4e87 mod_prometheus: Add my copyright.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 3135
diff changeset
     1
-- Log statistics to Prometheus
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
     2
--
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
     3
-- Copyright (C) 2014 Daurnimator
3136
4ef28b6b4e87 mod_prometheus: Add my copyright.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 3135
diff changeset
     4
-- Copyright (C) 2018 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
4548
64fa2dd34d43 mod_prometheus: remove space between label k/v pairs
Jonas Schäfer <jonas@wielicki.name>
parents: 4546
diff changeset
     5
-- Copyright (C) 2021 Jonas Schäfer <jonas@zombofant.net>
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
     6
--
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
     7
-- This module is MIT/X11 licensed.
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
     8
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
     9
module:set_global();
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    10
3132
a34e7bd87b39 mod_prometheus: Optimise global lookups.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 3131
diff changeset
    11
local tostring = tostring;
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    12
local t_insert = table.insert;
3132
a34e7bd87b39 mod_prometheus: Optimise global lookups.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 3131
diff changeset
    13
local t_concat = table.concat;
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    14
local socket = require "socket";
4546
fb4a50bf60f1 mod_prometheus: Invoke stats collection if in 'manual' mode
Kim Alvefur <zash@zash.se>
parents: 3956
diff changeset
    15
local statsman = require "core.statsmanager";
fb4a50bf60f1 mod_prometheus: Invoke stats collection if in 'manual' mode
Kim Alvefur <zash@zash.se>
parents: 3956
diff changeset
    16
local get_stats = statsman.get_stats;
4559
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    17
local get_metric_registry = statsman.get_metric_registry;
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    18
local collect = statsman.collect;
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    19
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    20
local function escape(text)
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    21
	return text:gsub("\\", "\\\\"):gsub("\"", "\\\""):gsub("\n", "\\n");
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    22
end
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    23
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    24
local function escape_name(name)
4559
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    25
	return name:gsub("/", "__"):gsub("[^A-Za-z0-9_]", "_"):gsub("^[^A-Za-z_]", "_%1");
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    26
end
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    27
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    28
local function get_timestamp()
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    29
	-- Using LuaSocket for that because os.time() only has second precision.
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    30
	return math.floor(socket.gettime() * 1000);
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    31
end
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    32
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    33
local function repr_help(metric, docstring)
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    34
	docstring = docstring:gsub("\\", "\\\\"):gsub("\n", "\\n");
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    35
	return "# HELP "..escape_name(metric).." "..docstring.."\n";
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    36
end
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    37
4559
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    38
local function repr_unit(metric, unit)
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    39
	if not unit then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    40
		unit = ""
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    41
	else
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    42
		unit = unit:gsub("\\", "\\\\"):gsub("\n", "\\n");
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    43
	end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    44
	return "# UNIT "..escape_name(metric).." "..unit.."\n";
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    45
end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    46
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    47
-- local allowed_types = { counter = true, gauge = true, histogram = true, summary = true, untyped = true };
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    48
-- local allowed_types = { "counter", "gauge", "histogram", "summary", "untyped" };
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    49
local function repr_type(metric, type_)
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    50
	-- if not allowed_types:contains(type_) then
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    51
	-- 	return;
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    52
	-- end
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    53
	return "# TYPE "..escape_name(metric).." "..type_.."\n";
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    54
end
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    55
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    56
local function repr_label(key, value)
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    57
	return key.."=\""..escape(value).."\"";
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    58
end
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    59
4559
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    60
local function repr_labels(labelkeys, labelvalues, extra_labels)
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    61
	local values = {}
4559
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    62
	if labelkeys then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    63
		for i, key in ipairs(labelkeys) do
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    64
			local value = labelvalues[i]
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    65
			t_insert(values, repr_label(escape_name(key), escape(value)));
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    66
		end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    67
	end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    68
	if extra_labels then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    69
		for key, value in pairs(extra_labels) do
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    70
			t_insert(values, repr_label(escape_name(key), escape(value)));
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    71
		end
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    72
	end
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    73
	if #values == 0 then
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    74
		return "";
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    75
	end
4548
64fa2dd34d43 mod_prometheus: remove space between label k/v pairs
Jonas Schäfer <jonas@wielicki.name>
parents: 4546
diff changeset
    76
	return "{"..t_concat(values, ",").."}";
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    77
end
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    78
4559
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    79
local function repr_sample(metric, labelkeys, labelvalues, extra_labels, value)
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    80
	return escape_name(metric)..repr_labels(labelkeys, labelvalues, extra_labels).." "..string.format("%.17g", value).."\n";
3153
ccbfe7df02dc mod_prometheus: Expose min, max and average when available.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 3142
diff changeset
    81
end
ccbfe7df02dc mod_prometheus: Expose min, max and average when available.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 3142
diff changeset
    82
4559
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    83
local get_metrics;
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    84
if statsman.get_metric_registry then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    85
	module:log("debug", "detected OpenMetrics statsmanager")
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    86
	-- Prosody 0.12+ with OpenMetrics
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    87
	function get_metrics(event)
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    88
		local response = event.response;
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    89
		response.headers.content_type = "application/openmetrics-text; version=0.0.4";
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    90
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    91
		if collect then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    92
			-- Ensure to get up-to-date samples when running in manual mode
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    93
			collect()
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    94
		end
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    95
4559
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    96
		local registry = get_metric_registry()
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    97
		if registry == nil then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    98
			response.headers.content_type = "text/plain; charset=utf-8"
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    99
			response.status_code = 404
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   100
			return "No statistics provider configured\n"
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   101
		end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   102
		local answer = {};
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   103
		for metric_family_name, metric_family in pairs(registry:get_metric_families()) do
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   104
			t_insert(answer, repr_help(metric_family_name, metric_family.description))
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   105
			t_insert(answer, repr_unit(metric_family_name, metric_family.unit))
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   106
			t_insert(answer, repr_type(metric_family_name, metric_family.type_))
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   107
			for labelset, metric in metric_family:iter_metrics() do
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   108
				for suffix, extra_labels, value in metric:iter_samples() do
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   109
					t_insert(answer, repr_sample(metric_family_name..suffix, metric_family.label_keys, labelset, extra_labels, value))
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   110
				end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   111
			end
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   112
		end
4559
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   113
		t_insert(answer, "# EOF\n")
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   114
		return t_concat(answer, "");
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   115
	end
4559
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   116
else
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   117
	module:log("debug", "detected pre-OpenMetrics statsmanager")
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   118
	-- Pre-OpenMetrics
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   119
4559
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   120
	local allowed_extras = { min = true, max = true, average = true };
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   121
	local function insert_extras(data, key, name, timestamp, extra)
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   122
		if not extra then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   123
			return false;
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   124
		end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   125
		local has_extra = false;
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   126
		for extra_name in pairs(allowed_extras) do
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   127
			if extra[extra_name] then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   128
				local field = {
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   129
					value = extra[extra_name],
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   130
					labels = {
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   131
						["type"] = name,
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   132
						field = extra_name,
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   133
					},
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   134
					typ = "gauge";
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   135
					timestamp = timestamp,
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   136
				};
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   137
				t_insert(data[key], field);
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   138
				has_extra = true;
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   139
			end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   140
		end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   141
		return has_extra;
4546
fb4a50bf60f1 mod_prometheus: Invoke stats collection if in 'manual' mode
Kim Alvefur <zash@zash.se>
parents: 3956
diff changeset
   142
	end
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   143
4559
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   144
	local function parse_stats()
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   145
		local timestamp = tostring(get_timestamp());
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   146
		local data = {};
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   147
		local stats, changed_only, extras = get_stats();
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   148
		for stat, value in pairs(stats) do
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   149
			-- module:log("debug", "changed_stats[%q] = %s", stat, tostring(value));
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   150
			local extra = extras[stat];
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   151
			local host, sect, name, typ = stat:match("^/([^/]+)/([^/]+)/(.+):(%a+)$");
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   152
			if host == nil then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   153
				sect, name, typ = stat:match("^([^.]+)%.(.+):(%a+)$");
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   154
			elseif host == "*" then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   155
				host = nil;
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   156
			end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   157
			if sect:find("^mod_measure_.") then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   158
				sect = sect:sub(13);
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   159
			elseif sect:find("^mod_statistics_.") then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   160
				sect = sect:sub(16);
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   161
			end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   162
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   163
			local key = escape_name("prosody_"..sect);
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   164
			local field = {
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   165
				value = value,
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   166
				labels = { ["type"] = name},
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   167
				-- TODO: Use the other types where it makes sense.
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   168
				typ = (typ == "rate" and "counter" or "gauge"),
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   169
				timestamp = timestamp,
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   170
			};
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   171
			if host then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   172
				field.labels.host = host;
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   173
			end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   174
			if data[key] == nil then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   175
				data[key] = {};
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   176
			end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   177
			if not insert_extras(data, key, name, timestamp, extra) then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   178
				t_insert(data[key], field);
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   179
			end
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   180
		end
4559
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   181
		return data;
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   182
	end
4559
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   183
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   184
	function get_metrics(event)
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   185
		local response = event.response;
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   186
		response.headers.content_type = "text/plain; version=0.0.4";
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   187
		if statsman.collect then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   188
			statsman.collect()
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   189
		end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   190
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   191
		local answer = {};
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   192
		for key, fields in pairs(parse_stats()) do
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   193
			t_insert(answer, repr_help(key, ""));
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   194
			t_insert(answer, repr_type(key, fields[1].typ));
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   195
			for _, field in pairs(fields) do
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   196
				t_insert(answer, repr_sample(key, nil, nil, field.labels, field.value, field.timestamp));
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   197
			end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   198
		end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   199
		return t_concat(answer, "");
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   200
	end
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   201
end
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   202
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   203
function module.add_host(module)
3956
343dc9dd70dd mod_prometheus: Ensure mod_http is loaded where the http interface is exposed (thanks Martin)
Kim Alvefur <zash@zash.se>
parents: 3153
diff changeset
   204
	module:depends "http";
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   205
	module:provides("http", {
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   206
		default_path = "metrics";
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   207
		route = {
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   208
			GET = get_metrics;
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   209
		};
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   210
	});
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   211
end