mod_prometheus/mod_prometheus.lua
author Matthew Wild <mwild1@gmail.com>
Fri, 23 Sep 2022 22:41:15 +0100
changeset 5058 62480053c87b
parent 4600 c406e4bf7ee5
permissions -rw-r--r--
mod_cloud_notify_encrypted: Additional debug logging when enabling/skipping
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