mod_prometheus/mod_prometheus.lua
author Kim Alvefur <zash@zash.se>
Sat, 19 Jun 2021 12:55:14 +0200
changeset 4599 bac3dae031ee
parent 4559 1e70538e4641
child 4600 c406e4bf7ee5
permissions -rw-r--r--
Add note of incompatibility with trunk since 5f15ab7c6ae5
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
4599
bac3dae031ee Add note of incompatibility with trunk since 5f15ab7c6ae5
Kim Alvefur <zash@zash.se>
parents: 4559
diff changeset
    20
assert(get_stats, "not compatible with trunk based on openmetrics");
bac3dae031ee Add note of incompatibility with trunk since 5f15ab7c6ae5
Kim Alvefur <zash@zash.se>
parents: 4559
diff changeset
    21
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    22
local function escape(text)
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    23
	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
    24
end
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    25
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    26
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
    27
	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
    28
end
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    29
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    30
local function get_timestamp()
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    31
	-- 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
    32
	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
    33
end
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    34
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    35
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
    36
	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
    37
	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
    38
end
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    39
4559
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    40
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
    41
	if not unit then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    42
		unit = ""
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    43
	else
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    44
		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
    45
	end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    46
	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
    47
end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    48
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    49
-- 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
    50
-- 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
    51
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
    52
	-- 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
    53
	-- 	return;
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
	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
    56
end
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    57
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    58
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
    59
	return key.."=\""..escape(value).."\"";
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    60
end
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    61
4559
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    62
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
    63
	local values = {}
4559
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    64
	if labelkeys then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    65
		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
    66
			local value = labelvalues[i]
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    67
			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
    68
		end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    69
	end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    70
	if extra_labels then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    71
		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
    72
			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
    73
		end
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    74
	end
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    75
	if #values == 0 then
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    76
		return "";
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    77
	end
4548
64fa2dd34d43 mod_prometheus: remove space between label k/v pairs
Jonas Schäfer <jonas@wielicki.name>
parents: 4546
diff changeset
    78
	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
    79
end
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    80
4559
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    81
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
    82
	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
    83
end
ccbfe7df02dc mod_prometheus: Expose min, max and average when available.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 3142
diff changeset
    84
4559
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    85
local get_metrics;
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    86
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
    87
	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
    88
	-- 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
    89
	function get_metrics(event)
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    90
		local response = event.response;
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    91
		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
    92
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    93
		if collect then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    94
			-- 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
    95
			collect()
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    96
		end
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
    97
4559
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
    98
		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
    99
		if registry == nil then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   100
			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
   101
			response.status_code = 404
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   102
			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
   103
		end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   104
		local answer = {};
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   105
		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
   106
			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
   107
			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
   108
			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
   109
			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
   110
				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
   111
					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
   112
				end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   113
			end
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   114
		end
4559
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   115
		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
   116
		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
   117
	end
4559
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   118
else
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   119
	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
   120
	-- Pre-OpenMetrics
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   121
4559
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   122
	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
   123
	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
   124
		if not extra then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   125
			return false;
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   126
		end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   127
		local has_extra = false;
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   128
		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
   129
			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
   130
				local field = {
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   131
					value = extra[extra_name],
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   132
					labels = {
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   133
						["type"] = name,
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   134
						field = extra_name,
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   135
					},
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   136
					typ = "gauge";
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   137
					timestamp = timestamp,
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   138
				};
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   139
				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
   140
				has_extra = true;
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   141
			end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   142
		end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   143
		return has_extra;
4546
fb4a50bf60f1 mod_prometheus: Invoke stats collection if in 'manual' mode
Kim Alvefur <zash@zash.se>
parents: 3956
diff changeset
   144
	end
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   145
4559
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   146
	local function parse_stats()
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   147
		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
   148
		local data = {};
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   149
		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
   150
		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
   151
			-- 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
   152
			local extra = extras[stat];
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   153
			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
   154
			if host == nil then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   155
				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
   156
			elseif host == "*" then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   157
				host = nil;
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   158
			end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   159
			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
   160
				sect = sect:sub(13);
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   161
			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
   162
				sect = sect:sub(16);
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   163
			end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   164
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   165
			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
   166
			local field = {
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   167
				value = value,
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   168
				labels = { ["type"] = name},
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   169
				-- 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
   170
				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
   171
				timestamp = timestamp,
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   172
			};
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   173
			if host then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   174
				field.labels.host = host;
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   175
			end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   176
			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
   177
				data[key] = {};
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   178
			end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   179
			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
   180
				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
   181
			end
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
		return data;
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   184
	end
4559
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   185
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   186
	function get_metrics(event)
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   187
		local response = event.response;
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   188
		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
   189
		if statsman.collect then
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   190
			statsman.collect()
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   191
		end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   192
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   193
		local answer = {};
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   194
		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
   195
			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
   196
			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
   197
			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
   198
				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
   199
			end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   200
		end
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   201
		return t_concat(answer, "");
1e70538e4641 mod_prometheus: Port to new OpenMetrics based statistics module
Jonas Schäfer <jonas@wielicki.name>
parents: 4548
diff changeset
   202
	end
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   203
end
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   204
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   205
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
   206
	module:depends "http";
3129
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   207
	module:provides("http", {
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   208
		default_path = "metrics";
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   209
		route = {
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   210
			GET = get_metrics;
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   211
		};
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   212
	});
07a2ba55de4d mod_prometheus: Add a new statistics export module, for Prometheus.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff changeset
   213
end